From 28da5b776fce24d8817244f086b8d6d760334ffb Mon Sep 17 00:00:00 2001 From: lukeIam Date: Wed, 2 Oct 2013 19:38:45 +0200 Subject: [PATCH 01/81] WCF-Server inital commit (Wenserver without usermanagement and with some pages) --- ClientServerLib/ClientServerLib/CServer.cs | 305 +++++--------- .../ClientServerLib/CWebservice.cs | 239 +++++++++++ .../ClientServerLib/ClientServerLib.csproj | 117 +++--- .../ClientServerLib/DataStructs.cs | 92 ++++ Output/ClientServerLib.dll | Bin 43008 -> 50688 bytes Vocaluxe.sln | 18 +- Vocaluxe/Base/CProfiles.cs | 42 +- Vocaluxe/Base/CSettings.cs | 25 +- Vocaluxe/Base/Server/CCommands.cs | 20 +- Vocaluxe/Base/Server/CVocaluxeServer.cs | 397 ++++++++++++------ Vocaluxe/Base/Server/VocaluxeStructs.cs | 4 +- Vocaluxe/Vocaluxe.csproj | 82 +++- Vocaluxe/Website/css/images/ajax-loader.gif | Bin 0 -> 7825 bytes .../Website/css/images/icons-18-black.png | Bin 0 -> 1968 bytes .../Website/css/images/icons-18-white.png | Bin 0 -> 1988 bytes .../Website/css/images/icons-36-black.png | Bin 0 -> 3859 bytes .../Website/css/images/icons-36-white.png | Bin 0 -> 3861 bytes .../Website/css/jquery.mobile-1.3.2.min.css | 12 + .../css/jquery.mobile.theme-1.3.2.min.css | 12 + Vocaluxe/Website/css/style.css | 41 ++ Vocaluxe/Website/img/admin.png | Bin 0 -> 15784 bytes Vocaluxe/Website/img/keyboard.png | Bin 0 -> 628 bytes Vocaluxe/Website/img/photo.png | Bin 0 -> 3486 bytes Vocaluxe/Website/img/profile.png | Bin 0 -> 163544 bytes Vocaluxe/Website/img/profiles.png | Bin 0 -> 12647 bytes Vocaluxe/Website/index.html | 156 +++++++ Vocaluxe/Website/js/jquery-1.9.1.min.js | 5 + .../Website/js/jquery.mobile-1.3.2.min.js | 9 + Vocaluxe/Website/js/main.js | 192 +++++++++ Vocaluxe/app.config | 12 +- VocaluxeLib/Profile/CAvatar.cs | 29 +- 31 files changed, 1371 insertions(+), 438 deletions(-) create mode 100644 ClientServerLib/ClientServerLib/CWebservice.cs create mode 100644 ClientServerLib/ClientServerLib/DataStructs.cs create mode 100644 Vocaluxe/Website/css/images/ajax-loader.gif create mode 100644 Vocaluxe/Website/css/images/icons-18-black.png create mode 100644 Vocaluxe/Website/css/images/icons-18-white.png create mode 100644 Vocaluxe/Website/css/images/icons-36-black.png create mode 100644 Vocaluxe/Website/css/images/icons-36-white.png create mode 100644 Vocaluxe/Website/css/jquery.mobile-1.3.2.min.css create mode 100644 Vocaluxe/Website/css/jquery.mobile.theme-1.3.2.min.css create mode 100644 Vocaluxe/Website/css/style.css create mode 100644 Vocaluxe/Website/img/admin.png create mode 100644 Vocaluxe/Website/img/keyboard.png create mode 100644 Vocaluxe/Website/img/photo.png create mode 100644 Vocaluxe/Website/img/profile.png create mode 100644 Vocaluxe/Website/img/profiles.png create mode 100644 Vocaluxe/Website/index.html create mode 100644 Vocaluxe/Website/js/jquery-1.9.1.min.js create mode 100644 Vocaluxe/Website/js/jquery.mobile-1.3.2.min.js create mode 100644 Vocaluxe/Website/js/main.js diff --git a/ClientServerLib/ClientServerLib/CServer.cs b/ClientServerLib/ClientServerLib/CServer.cs index d8cba3f2..903a00e0 100644 --- a/ClientServerLib/ClientServerLib/CServer.cs +++ b/ClientServerLib/ClientServerLib/CServer.cs @@ -1,194 +1,111 @@ -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 CServer - { - private TcpListener tcpListener; - private Thread listenThread; - private int port; - private bool encryption; - private string password; - private int bufferLength = 8192; - private bool running; - - private HandleRequest requestCallback; - - private Dictionary clients; - private Queue ids; - - public CServer(HandleRequest RequestCallback, int Port = 3000, string Password = null) - { - port = Port; - running = false; - requestCallback = RequestCallback; - encryption = Password != null; - password = Password; - - clients = new Dictionary(); - ids = new Queue(1000); - - for (int i = 0; i < 1000; i++) - ids.Enqueue(i); - } - - public void Start() - { - if (!running) - { - running = true; - - tcpListener = new TcpListener(IPAddress.Any, port); - - listenThread = new Thread(new ThreadStart(ListenForClients)); - listenThread.Start(); - } - } - - public void Stop() - { - if (running) - { - 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); - } - } - } - } - - private void ListenForClients() - { - tcpListener.Start(); - TcpClient client; - - while (running) - { - //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) - { - 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(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; - } - } - } - } - - private byte[] HandleClientMessage(byte[] Message, CConnection connection) - { - return requestCallback(connection.ConnectionID, Message); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.ServiceModel; +using System.ServiceModel.Description; +using System.ServiceModel.Web; + +namespace ClientServerLib +{ + public class CServer + { + private ServiceHost host; + private Uri baseAddress; + + private static SendKeyEventDelegate sendKeyEvent; + public static SendKeyEventDelegate SendKeyEvent + { + internal get { return CServer.sendKeyEvent; } + set { CServer.sendKeyEvent = value; } + } + + #region profile + + 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; } + } + + #endregion + + public CServer(int port) + { + baseAddress = new Uri("http://localhost:" + port + "/"); + host = new WebServiceHost(typeof(CWebservice), baseAddress); + WebHttpBinding wb = new WebHttpBinding(); + wb.MaxReceivedMessageSize = 10485760; + wb.MaxBufferSize = 10485760; + host.AddServiceEndpoint(typeof(ICWebservice), wb, "Vocaluxe"); + } + + public void Start() + { + try + { + // Step 4 Enable metadata exchange. + ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); + smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15; + smb.HttpGetEnabled = true; + host.Description.Behaviors.Add(smb); + + // Step 5 Start the service. + host.Open(); + } + catch (CommunicationException ce) + { + host.Abort(); + } + } + + public void Stop() + { + try + { + host.Close(); + } + catch (CommunicationException ce) + { + host.Abort(); + } + } + } +} diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs new file mode 100644 index 00000000..b10e0ae8 --- /dev/null +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -0,0 +1,239 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.ServiceModel; +using System.Text; +using System.ServiceModel.Web; +using System.Web.Services; +using System.IO; + +namespace ClientServerLib +{ + [ServiceContract(Name = "Vocaluxe")] + public interface ICWebservice + { + [OperationContract] + [WebInvoke(Method = "GET", + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/sendKeyEvent?key={key}")] + bool sendKeyEvent(string key); + + #region profile + + [OperationContract] + [WebInvoke(Method = "POST", + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/sendProfile")] + bool sendProfile(ProfileData profile); + + [OperationContract] + [WebInvoke(Method = "GET", + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/getProfile?profileId={profileId}")] + ProfileData getProfile(int profileId); + + [OperationContract] + [WebInvoke(Method = "GET", + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/getProfileList")] + ProfileData[] getProfileList(); + + #endregion + + #region photo + + [OperationContract] + [WebInvoke(Method = "POST", + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/sendPhoto")] + bool sendPhoto(PhotoData photo); + + #endregion + + #region website + + [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); + + #endregion + } + + class CWebservice : ICWebservice + { + public CWebservice() + { + } + + public bool sendKeyEvent(string key) + { + if (CServer.SendKeyEvent == null) + { + return false; + } + return CServer.SendKeyEvent(key); + } + + #region profile + + public bool sendProfile(ProfileData profile) + { + if (CServer.SendProfileData == null) + { + return false; + } + return CServer.SendProfileData(profile); + } + + public ProfileData getProfile(int profileId) + { + if (CServer.GetProfileData == null) + { + return new ProfileData(); + } + return CServer.GetProfileData(profileId); + } + + public ProfileData[] getProfileList() + { + if (CServer.GetProfileList == null) + { + return new ProfileData[]{}; + } + return CServer.GetProfileList(); + } + + #endregion + + #region photo + + public bool sendPhoto(PhotoData photo) + { + return CServer.SendPhoto(photo); + } + + #endregion + + #region website + + 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"; + } + + byte[] data = CServer.GetSiteFile("js/" + filename); + + if (data != null) + { + return new MemoryStream(data); + } + else + { + 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"; + } + + byte[] data = CServer.GetSiteFile("css/" + filename); + + if (data != null) + { + return new MemoryStream(data); + } + else + { + 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"; + } + + byte[] data = CServer.GetSiteFile("css\\images\\" + filename); + + if (data != null) + { + return new MemoryStream(data); + } + else + { + 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"; + } + + byte[] data = CServer.GetSiteFile("img/" + filename); + + if (data != null) + { + return new MemoryStream(data); + } + else + { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound; + return null; + } + } + + #endregion + } +} diff --git a/ClientServerLib/ClientServerLib/ClientServerLib.csproj b/ClientServerLib/ClientServerLib/ClientServerLib.csproj index 8b4826b3..f0625c63 100644 --- a/ClientServerLib/ClientServerLib/ClientServerLib.csproj +++ b/ClientServerLib/ClientServerLib/ClientServerLib.csproj @@ -1,61 +1,70 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3} - Library - Properties - ClientServerLib - ClientServerLib - v4.0 - 512 - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - - + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {EC5167E4-CCFB-4CEE-987C-CF816F1062A3} + Library + Properties + ClientServerLib + ClientServerLib + v4.0 + 512 + + + + + true + full + false + bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + --> \ No newline at end of file diff --git a/ClientServerLib/ClientServerLib/DataStructs.cs b/ClientServerLib/ClientServerLib/DataStructs.cs new file mode 100644 index 00000000..a5a97d2e --- /dev/null +++ b/ClientServerLib/ClientServerLib/DataStructs.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.Serialization; +using System.Drawing; +using System.IO; +using System.Drawing.Imaging; +using System.Text.RegularExpressions; + +namespace ClientServerLib +{ + public delegate bool SendKeyEventDelegate(string key); + + + #region profile + + public delegate ProfileData GetProfileDataDelegate(int profileId); + public delegate bool SendProfileDataDelegate(ProfileData profile); + public delegate ProfileData[] GetProfileListDelegate(); + + [DataContract] + public struct ProfileData + { + [DataMember] + public Base64Image Avatar; + [DataMember] + public string PlayerName; + [DataMember] + public int Type; + [DataMember] + public int Difficulty; + [DataMember] + public int ProfileId; + [DataMember] + public bool IsEditable; + } + + #endregion + + #region photo + + public delegate bool SendPhotoDelegate(PhotoData photo); + + [DataContract] + public struct PhotoData + { + [DataMember] + public Base64Image Photo; + //Add infomation about the user who took this image?? + } + + #endregion + + #region website + + public delegate byte[] GetSiteFileDelegate(string filename); + + #endregion + + [DataContract] + public class Base64Image + { + [DataMember] + private string base64Data = ""; + + public Base64Image(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 Image getImage() + { + byte[] imageData = Convert.FromBase64String(base64Data); + 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[1].Value : ""; + } + + + } +} diff --git a/Output/ClientServerLib.dll b/Output/ClientServerLib.dll index 69ccb313a64935f7833a2b6a4df3c01e554dc47d..8a30dec5e8e5f512140264b571843a090bfda90c 100644 GIT binary patch literal 50688 zcmdSC3w&HvwLiY+oHOT~d1lT`GL!U`)V2^hO`7yYD5W%g2l{?M0>w0sX`7N{(wU^R z#9*R;pcbvr3J4V{3aBU#xuAfG0zQxn2tM#pzz5)!dxf9+Q!jt;|6ObEb7s<{px)o_ z|Nl_fd-mFowbx#I?X}llXP=X`=Y3r0LI?xl?|&EKe*DtEB^qbC<=3L(D}g7b z-tSxU#MCXjy7EgugpzJ7C6Pqs5t8;Jy`E7TiS z2(iYei>3d*Vw2n33qqS3@`Z%>I&w^z`}JSow+i6}1R-La)+F7OLG<&#DxVO@r+>Ow zav4>n{|mngq%8c~1-zRn@q!Qy#E3Efd?Jjzx}OU%X-wJMWK;=Z7ZuxpR~Nyx{h59J zfFF4f5z2V1if%ysuS$sRwYhw*0}#{p0unUPZz2@^TY~AT&1Jf?s7SO5p?L5J175U5 zh@~E&5;qZF@sDWJgkL;+g%H~?6Tt8<{Y%tIexbc1v_YDoU|N_n^*TfJDvVkcjd%zn zF|>SKh~N;YHneI=f{Nr28XNeb##(9!vx0gFs)u4X3GpyAZIF;0s0O`5m}HcdqFPxg zVKs*W$PqJzNYv@#QuM88BJ4r4W}nca#!!S>Mg2oj{xye6=vN=I=*Jkc>1UAe__Gel zBFJIl2K~q@ean}8%Li1mD4)sH-ZIhD%$I?Te3D3}iW*nXrT~MCnG@?YF^mMpM?4~g zz!SD>_PB#j2DL%r$&5%`RF`uzZIA|^tzh6-%#kL;yaD=9JB{#91$09m4Q?(F7%-@K~-EBLyi1fIS;nVwLzNv{ABb!1RbQrU=aLAk}|SWh%8Jzi)l4zCslQ9)k#8=97u-J zX>?9PkY8*3yo!Qq3W&>QA8WEdz4!J#maEA9)l&h7 ztXbt&7UK!dipk%rx{_~cYN%AZX18z)QoI;BvqWVkuMeld;1xo_2{W0n(kDBnV_hE+ zf$TJ3E-y5*L;&^EWx~O9BrL~r%&WTIG8pCKAS$f^+cE!1m}LBK3d7!rb!R4wv~UcF zqM)^ezQmXRP55g8YDnMrbruT|g8o}h#r#j|6c(oJbWj0&3h!7A<|;y^7NwxgB)KQn zmL-K>^3@PCFq@D;(kY~}82zkx5s;mMzS6#=NZ5{DV<|Z;u7JS>p?j!#7OK#siVKIS zt7J%EO^}jJO0Anc8FfSAn01o)`r=T?x7!<3WL@;i8O=TCexcg(J4ygqmmhA*x-2?imR<;I} zAe79g_x>Fwlsl7 zTTD;Q)dIxRv?$`eVPg{lFMVr>qvwk9tgygh$m<`)w4@Ic0&Jqz_nr+hEyRz+7lwT- zXPP+TTlpI)eVVw^cWFf9`V;H?;xd}@(Yn6GH%Q7}X?#F5-cfr0c_8b3HF^Y;o^e2`)oezLzI7@K5(QcEyW zhfT2-aY6ae) zq=`DlY?OjLs+q&I^=0RwIGA3n4Z^A{%vhOLMI6uH32s#1jcAC9Wjk3lJ0A^IYnb5Z z%MkaWFQ^|!sG-8zuu4M>M`>u>rJmHGfEQ4gCU;+bD$)>R)SN-%WZtBhH)^LrJ>3W%CX1@Yzu)n-BnY6a(OaWR2Rt);k^lF&EW;H~@feR8aumpj}l)c*%6atKa#^QkNw;hbCp7ffHGf2ly5*}5ehIy=g>=+%(9kva^XpFwQ4Fw#<7)<+S%1Ctd^1?H8>~Wn$Z~Bv2z`pB!S0-mP(3PvSi+9$&z`l zWSu0yP1uJlOtPpTOhM9dz9l423E!EUT$|AHweE1!!guk-u6_85_}o=KWkcR8UN|K4 zY3{!RJkT=UenTc(jipB#zKjB92w0g)_k&;R@Y$ua9=t(<;EH#04 zM2&1k^nkX?q}{0Pl&Koixd#c9TS&^ap;n~iv;W}%y}G89guXWQ+qV4lCU7Lqx6db0l3O+tv zyceUSf1aJ>AA$>oTxwJ3#~1?t$h4}WpZq$s9eNKX2RVMrJPA8wem%0Y8)!5#e;T8_ z;xkLK8!1!FT&N1Nn+TqHjtg$)HWK^HDUybn>$Jh8+yyoYqZ+4Ha!%3yeJ;>q=X3H< zXlBqfhNyz64N+}iBoZ-IY#h&l8Nno*Z<#+N5@E_H2VW(sVR%#NXOIBp=aYS4grrj) zQC?o@WQk%rR|%VR>SDQ z){H%G2PJS?qiV%?p~%2R6NH=DorFmoOX3LTVzRtk9$FPz&x%^vU8t#-p9h`51`PUK zsNpoOBrU*1l*`U8fhlHO(uD@Hqcl!@M8qX9;fnLsIcJJ^_K9-$2rFw-qhaXBQsP)>kXjzxs_5YR$70bV(*OO#__ z7Rm|m%0U>)VPO@@3Gm86F3Lf0p_~Ae`^85>3kNcpovMkN$k${0T2?%?xD0cNR^(l zTuf$eCwj`}P<9f8oX(YyYXPpKhkTxKW&80{J%A{?7ZEm(>_zk|ab@>W!G1($_Tr-K zK}w5bPROnIKAFLe5Z9Nsa+Pqf4so9K!FwqLRtfr5h=&vgucrbAw|&f!?Pt17WIaQ> z1xyXXRgLK&L6%y@5C3O6%6WPgdP1EHNS=z@K+?vvp*%ec%`vJCazz#QlP+!(5pnIU zvIs_EQ-4&Zlj0oJ7L*Ar0?;_SxNT4*4^YcsI>H56%*Uv9V30iblYansp#p;uoh4G>4Mv8KN{Sbu%DwL8OAB`YObBO-bM_^I4Lvj{&5UakU0-T=pQK zTqW=@vg{`SX0JvR(sDR9^;x+y5X+Ne^)<+^K7@$-6wsdrpSQ5i$tOXCR3AohkS)6W zCkc&JbQHEy)z=~~Y)8^$Qu2Clz}T=Exb1WBdG}Rc$4Ii*S6d|<`;25tDJM72W*v@si6fZBfEiU{crSjGWvSECVCKCCpBWfAY&dRP%rCk z?Kz@XR&~UD+6>N0HB0Pza(69!{Zy-Rj@*Z_*dK-!&L=peYheKIo?EI7628j%LscMT zxE0!v_H2}ga@S$l`6C$B#UkBEEtLf}U+87K=T4R_Wgn@QLi=JAzbv4T6;UV^t_35m zm=Cw2do204<-N#L``Qc)AhSH-IZR=J=%fZU>cHJt+Z>+spw^A(!r_k@g<|D$I z&=Rs!&0$OWVu1TGQ$DsuQVmx2o@&8K`AB-bDId?Gc*5wVkK!rqdJ0(6GtCN?Jyfb3 zQwc<%7Ew@6b-kgsFdI~7^~d#n2m@D+*e9jVG)3D9cxot)8t=%@x{v{mF;^Ax6LQu_ zwY;nND)|VmNr`b)*1yPZ-lL#Y=$X=ZGF&uuN=jkUosgHVKm~ETAtB|%(pd?%1nJrZ z76Gkup!n54NiUkPcz|Ac=V=z`6`E9*bm!@~{N2zxY|KzTjA|k4EA2`RkT<%lH}5s# zGDDmWIjo_6SR1=)Tq^uJTmGh%au>|0XrL|eW8P6_*PN`EsxK{WhP|9| z;${Nje4?^G0cQ&76vt4zyrkL#=e|d__cD&FE+1wvHcRAjFbH03Cj5Bn>X*-u{s4aB zOi%N5Aq!jKhVRe|*?sk-O1T+@r=$mva6U89H+u8EUawBBR77po}(Vfj_l7l!oaO z8b_$^hEOR^LH1eP!f6***%6jP;xHq6#jKpe%>36_ISwa}lc(B$oU!A|(`%3?oSX~t zMB+4iv^cdKCr-pE9-Wp{Vm0eHq58%cp|V_|`aiU+X8q&ihCn?uMxe+K*@_cX9gV%R z9$GdTR$^in>~nrZ5f-VCR(%OpTMQ;4ukLZGgmqa3GV0!>VO19qNjTBTWLN01^0Crr zvC+c|e*+HgBDtHdaX1F9Vl)-%DV67#hkDNoNVQ@?{W<>TgzdtP&1>ATE2}yaemo__ z9WY!J5x6?h3Ytr9J(y$ET)2|&21QO1x#vA5 zih!)58nb{0xGS}>aUV7mjZ`GjfYPl}mCCA6rIH8*7E~z__=GGwj?oLRAwF7mt!k=@ znVoExQ`22SVJzZuAQ4RWi&P?j$w*H|1*N0iY0#62fH!`ZpxK5KV6QA;ecTDSmHmVb zhu$KNShiwpFu-Df3S3J#cp@e5*V*E%P4a%7z|)4uru!n$<394$RAEf;LV0V@l!{5O zh9}Tu4w}lZV+cBz;GhnftqN*ab%oLfOjYRo`k;n{w;RDxUGtJ2PVW=8DbE9x14mkN zcZ66lQ)rOGUbFJd)^;+;1KV*I4Uhl)QkeV@rijN63!*^HA158@&fjkhTR33W0Uu%?tQfCRv21I<#P{LpykmE!y93ZuynV zjDONjK+`8pdAoyr0~4S#p{LL<>yXsknCvd86eX{0vaiCdQ4{`#-+@wP0KGktyiL83 zl0r}0wOaSRn4I0sVHcJ<6e_eMB9$Q6x4V`O{K_H3c)od@SjyI(luC6&bcS+{?jG*{ zMHX>~Pk81J>}!o}Z?Fn{(zCa~GA#I*HNHe%Tm~suHoGo5!L3uNow_>(_8Ty*H|hOx za*<1}t2IO?XDXZzzE-K7$U3B?;1D0IsW>T@g}YOr(K9KYP&x;YZ#}?t$_H+r9Yw1y zeui@R4SC;{EOpiVtmK&e6$7F9M-Nsq+;B5ZJWrzAq$V+@iK=gaqWlYkiK9gp`?e| zHyo})hr_yZ~IVS!n2(*;~#ZKB*MuX%xP)8l5bQfiKM z=!koB-j!#r_e)%H;Vt+i9SJ<|F=IYUcGr@yAv%e`aU}F6g2g%IEr)s&Aw^(wBJ6~j z{6wVTOt1?NpK)BPtZK(E$nR}VM4hM;+?FVzpZ6wW$%K>M2AjokN~WSZu~^hrI3-T# zJSQgGQ4h^;kqok(LZido){@lj7GQ}v@IA(ynAi9%zDZ7%VD4a%Iu080P_IiS;_0{( zapEAxiMN0waj-D%#GNoUK5FtSCqhp}%|t?XN~-&iVxMH9G>wa}s>f2jdM{Ne#j_44 z!6LwIk2wjaR2G#{Pg7(sP8qKz$)NFj{V~+(3{YY^B|S%oPk10sJ0x8|q74p|ExZTs zZWxX<9FmEoAvckhL@HfjNPV9)ofL+YLc^4k1iGY?QX3`>?YVT!t(ZKb%9DJAqtf4` zqsA!nRdrBbDjT`|dAmF{dP3%czb=a{Lpt$sC)!`_89Jaho$xCvZ6^sTC4EW1Yq}G< zU#4SjrST|)VMY7sUmzh1i`NYuYSN{$C2lOx-e(^wI-!!a@FLzpphJSP)cvD|Dv5xl zE^#Puv_bQP6#3+#-iTYCFch^gG1}d&0eEVS=)W)x(uTVqO5${q0qJMsI8<4WQ$5Un zR|Kk1iJxDwl@Y;x2zk0q;qt1SO}pp}%$65kZQ?q<6sqghq_s)1sSIzwz+zp7mLx~& zeI{84eE1*(d4kkcQcH1x4*88qc#$)EPSmJZ4Bogi;fVGPpHlY3yQ(7xnm~f7O(v#xNzl_r3nl(7F9xLTB6m2XxY#oI)(7 zc~_=#R@OfR1k)GMcZ&v;m;g>q-oA?9=Bg3j$nGRRNzLmG66 zJ%$KwQYN4sY$he_dBLP6N*L#f`U03s zI0a+xWPReu9U*zBGAOMYYLW7CKT4-}s~TRnU?@EWSL>Nxs@=j*bUzCF#VvOXcq=3= zb(2p>R1z;3;K>2HS(t-IgVg}_8P44UDlNXNgFCP8aaz42v{r38kme8z+45mUSL*>u`5LoWbDyked{2^B<}sHQNG@ zVs4l6+>V_pa%Y8d4+ELJvXJ6O%)ulsK~QJKvL&5`O1&D@ABF&hQely{H3i5`aZD52 zkP2DjS&yi#wmo6Ep10Hy*yZX5M!=|sXUB}_*=zB`o=|Mh4d0=OPbF-)<{EH>bbYU| z*B$A_p>f1CY%%n3+z8Os7BdL*upQSktx>rl`Lr3H1^G-mc}Q+kJg0+IRQBU%iaxRI(Ena`B)CekRFdn-4(gDT>2>IU0ERjwrt_ABr61@dYI~ z8r1v{M;MYeyVx^JhBXyh0co-Z{L<7n_`#D}wkPosXx*+-C z$+W)D`WtZ1iac;3c;Uk|zBNS^dzJAA2i$p1P&N;fD?ZemhV zSQ?AY@Q@j#oJ{8FD~_EgfdrS3ZK{a_VDR#S{u|XH`BnqciVLPSO`W61R*`00D6Q!s zE1ZtvwOY$$wG^~N>S2E1pKMUmQ0|YO@`MeCSJg=hZ6gco+mz=k_;=Y~{2M6ch$>GO9lZ$6D_$3C zMGCqcy|$~mSk^`E=zw%bmsM6-RH<|PO0Dd(7HM^xWHgE@@P1gL(Oe(9Tzk9%h#dF& z1KY75K>d}(kAL!V0T22KIbe5#I~3&JLzPwGbPzUeOV~;kjlL&VMz@vMrf?X!uupOPa z5>sC5Rh9R2c*%0r6spcgRj)2@7$hzprX*qF?JUIFCv2+QXuM1!c|0pXg}QVuC1oc{sUhyvWmG?lGFmPo1&FYTq~Dr=1QG}_QSLiH5A zn9b)jLh@6xzB{btyz>Cv~9L z&g;{}D8jg&EM0JpUza0TSOKL4zCjs;S-vjAUbgxK^OgmC$DL0P(@$tVi>DBt6+9?E3-$@`g>~wpT;Pyn@DnC#2?LG!97#{c77XKu z?gn_AVLO4UJ%W3C#rNYV?^b*)W{{X~N-0WMYEP7sgU6Wi4MA`_1ScW!9CMld8k#uP zh39pVvyp^{aJ>v&9Y!Hb50pJEFq&tY%LvV-Yk*@(c=AIHAwSr}LL}G(Ugx+1L^}d6 zQ#6))gC_`FlbL@D7H?Dwq0reU!&+3no~t7GXj z+@B?EjYzGZD1jFf`>TWf%5ogsePl@_R1Y~ZCI-?RCxHy28bp}{62%L@1+O6{9s(Jc z_7(i~nB=At$Rq}OVwt4EcaTY{0=7gN_L3y2!H=(FxM~Vj&mLDMJxsF*(`X$d?~3k4 zek72R0%S;up|3HF>0^ZE?V9R(|iI8np9|gG*3OgYuTs;if z?U4~-qU8+;lO`I?7lv5#U@LJV>?hU4&0xb>bIR;s+8iBox1=?UEqJ!I;fe|xE(Ja_=CVdN}sAn$ar|f3alL>65*L}qA+hGh?RXC(fLrCh)A08ArpG$;e>T3lC1s$ zu|{gNCYMVu0(7mL=l+q}UKb4P+k+Xf4X^poc1W(vrHK z0&6_=)2I+a`+W!uw`u_??*l$ASW<=5*hB1hrz zDVFfv=P4onFtHyGr?{Ijc!Ew`wnr5jUEI?W)C(Sc#hA+pXoLi85lzriT0`q=9RCOT zPKz}H7WfKr32u8B)-|k%aOIQ_Jj5ERtfl9hHcv$)ki7|n$|>hEGLDQiYz2Ch$w>Ii zKGf_Bcn9rzS(~f+VOXSPeR3`H8KnWsZS4u@qyt+qoyD4q&tmVeKT&%u$C3v6(8k+p zFve!5Q1$k4_a_h2hfz%W@PzE5np(PHTz2tzz^;;pWz@@Y9HY|PM%iQD(_d02q*_Rw zs6)GX$l+rKQx0_^PvS7SE8%cxhn>xy5g03^Rp=reWS)9}I#GLxYNGOQWIrUEXRwjk zXB8}0dlYsh*KURrA>xF+MG+pmD5w*xL_C^_rt4uD<7E$eeomr9MP%|s(zB2sE;e~E z0%$2xTs1g^!wpsNCOiP;q#6g*MnaaJI)sy~lRr36kfG!u&mXMQ8W8KKEV&y_NU5-T z@y?-4r}#R7_Q$L&UA7n(3t3&8Qm+OwNGCWllJF$H-)GsMA>Y(68(&+=$`xF z-Q$WlBk{RUOY#hQPqwJANw_-}nN*6{@?v5W(q*A`V6%bFeZ^TBVAqhBq-*?3MT!m$ z^l?REuB9%cQBU-CE{!OZE{FdTr^V)=JQc7oQjPDAzH!6Ee;ISkVrZlielyiNYnsc^ z$*mQ&@d7YWDPraRAbfgRLb(W&hbmet<|fo?VW^?{NT^3M|M}P}S!MFAIQU8S4Cw7XAHFbDXb4qCjmqsN8wU>?}6DO86q z*|;`H2_>Z}DL!5jm7&~~w9qlJc*o&{LnUVgwI8+3Q}dt`P}@AJc#d+KuTwE!n`yo@ zdS4Z9Pgmeok;!aOLcQ1E#w^_=s)jbgWXQGXx}6Tu=380bS@n0!O)I`hOR9$&1?>Rt zEZ}zF4{tz)*gI61@($&1hhCCW-hxHbsx$>IfG7NRpaR#lWlJJr3a)$Gf%0+kQsd+m zTGFNl^mD2itH;;CNIbj=bcGZ8 zop2ua<{Z5i$F%$he$OeE5%%H9Ex}B6LjTgez|NpKu`^^6RqEhi;8F;ml1MSyRlqVF zNk>G=Cf-CyvS43G-#pzA^QZTS^cK$&@fR^I(8m5+EKP%Vca85$5ibb!M5Sb%ahk}B zZAEl^TGBzTrQ*xLgl7a#Gu+G9be7byHqNDSyV_h`Ybm(M!8k0ano~suYdhSGRJzMd zNh8NE4;p5<)O;?8k4oMOc1R7ZR8o6bK5DU3M=V%Z{N%v$^T8^_H&W8;VB?T)B0UEb z(L~}|j^pRGN>qdtoiK(cV|2KyF4dE=%XoLBdfx(zVH2UX92YD#%07yxg1kXmn(kPB ze07>nZurzBeQA<(#h+nQHxob9XeAMFXSusPeKjtWyV)~I3^w@WVvsKTa4}odaZxe_ zdR`^4d*VYhg*!)J7JV*EG@MT{^h>}l+K;GDf5Qe8DW2HMR6xN(x?zGftWM<$zZp<4 zF7dN8@opgtBT#8>?Wn;=NYZk6c*Zr0j*uR)?8RX!$R}Njx(cn|MSu+1T(vROcWxas zz*teAY^HyJyoBE$kZoM#5qdOSIM}LDNY@e(6%)GKE65Y$(+58UF7Laml^Ayj9=|H^ zZWsnM-yx(cgslFkbPr1ZdEz4lsvyPxAgkzf(vB%qqvquVh3qo!e?D~gBooEifWNo* z2{Vap-b@9Kn&pmh6psL~0s{2?sbtaD7UY*0NJGNPL4ezdzIRRE#^vt>Mes{^yAud0 zgvkh%2s02)K}aLuT{3!yfbO8tJt%r!P0wxk`+cza`EM4q;I|DSgRm3fLWCZKJqS4e zhz}xMiSQAGLkMt0iW?C=gFq_g4upFU?nU?p!ovuUB76to8HDE%evR;3gx?|j0pWFo zHxPVSRP@2O2to-$83KL#Zz2MHXK*e8*$<~7;L{m`e6Sl4Xq{ewK<`uUM93lxAPgeB zAK@~D0|*BZ@M^sH48ms-zKn1e!hHx2AUurlJ%lF^ofF5W)e3s}T+% z+>G#9gfAe_-2%KNCmuz365%HZzeM;o!pjJMKpt;zR)ijeJqUS(ix577@G*o>BHWB{JHj0ZxK$&*itrtT#}S@J_zA-E z2){*m9pTRiZy>yhU>V>SLJ2|z!bF4_2qz=dAe@P?3}FRA6T*6gtq2z&bRcvgydPl% z;UfrFBixAa8HC#r?m~D7;bDaDAUuKaB*KpnUPSmk!kY+xN6`JC1tEmsAe14b5GEp= zjBpCVY=n&n=OSEykU_WzVFcl02v;KY|iga;75jqp8$ClH=Q=&hQK)pKAKBz4A9 zE3k=He;#LyVRG8x3@YDwhb|+3AFi3okBXh6RnZ0ep$25QU*i!obK~UVn|V|TmShOH z%AiyDpH}^EbhZ-5Y>kWz`qLJqNy-0#B_l#`j8i?jclR`Yp##ysHb|%{r(AL>eyTqM z1Vg700psLDp&Hsm_E8MslDConB08b>=&3>F^eo-&%R)2aV|%%$VXdgNHb|9EST2jT zLB`Ig_-P%kQdpzf&|k5@H>hCNTi(|eHIrZO8G@QOw6J{bMUD4UBJm~n?^+ll2F9L8 zekc9M9EnOV&$W))8>oOgw3#ouU=UmL?03l-;- zY_mL1BAO?QSdE-t4Xj;b&-EeG zI-i$HZ5|d(aF}}YKKQwG^I1!M{F;yadq{id)z;O{t(#j94v{5>6(YV{3H=Rb&Z`pQ z*$SjL_vgBLcjl>v4UYU2`_Htko5c&j4Amp1t=ihO9KWvt?oI$++D)I7f zrv!ok|9i$<`Vb`MNWgHXZwRul?pgf)6#-i;+gwz&9)aq;7XjU|ZRn^p%JEM)ev#vowWJmlE49-#Q(UFxk)Enk`ceI>I{svd@v^9pJzYDz#JRb}9 zg-sEPzK$(%L3Dc56l*!&&GD5SALaM~j(^PY>l_D5sO=PvXO&Rf6&w$gw3l2ht}LO^ z-CuHTi79@{@&7I%O5P|*ViZ=4M%NHK9q}TLGcg*=WicAX$2k2(q)qWW$Cg9s84iuT zfzxL?M1PC(kd+h{bNVul@8@w${5i?9mg);n5y{lIl5ufHisrOAMHF6%I4N#OeH`Y^t*Jb?{U68ypUWqg z2gOp3S95$G#{-B>@u6~RdlkoD<@j-qpW=9J1@U291=V?f1iqm;ikk5i0@t#D78pd^kx_?1Pm1aGHuBuGM0QH)^Gbw`=8yJ2-!rHWBGVS|#Em z9N(s$jP$>0GZBAZt3~{@HV5%9v;~Mii8Y3rI;D?t`VO72{hQv0_=kEw;-Beoq>H$* zPnghM?}KDa_m?BCLF^N!a=e7&O@5-S*-y0X!dmr-{eEype9Hd>;*|Mu`WfNhrf zN5town$Hm*Hyy;^HLDQ6Y0gGG&06fEKk)Pe#38#J{U&W#O=2R)CvjY7V`memqmEBB zqRz(Q>yf`e++qVMMu!_H;w#8;#J4<@Sr(LSWt{q4Gayivj&cLO5$e z@jZ66P*h(J=qZLq!~~QDMBj8-Gp(NsXx9vaM#PyY3yJS4 zXbnTF@fd*0_V`*+_A0qC05zj5ES8hOLuL97Kp$1m5TJ;7mZ8h-1;#==Q+-uIjm9t_ zyl91gm)o0+O94%n5XN^Ubi%NNM5}QShTE$O>NXAox^ot{6Yn#2z{k>1BcYF?tW-2B z=o&y}Vjn{z;s)bJY}&6X=vI`Ki|uvPZbaM(s6uR;BcZPXnjqH9mC&~VO%zLTB7(=F zygR&cba6T8yhHuPNL@VUd)2syZ2>BK%op{4RaB{(kNGC}zb&SVHH?MYJq=IL zzexyZ)y4SUc!6$RAw~*`i*Kg+gj?IBi>MDXIiTO8KkT`q_d%m&na%sN&H3LkgIWzSj%ilAeFxN9!^9UvHq{O>XU-vFI1wn)l&{VfvP8G6Y_lr0k1D2OOK zLwr|3MA>2i!NuqVv&M~vNOdt1rcRS#BB;9%9e;pu+gaeS&-Th*HTL?}dQjAV)VI!q zCiuVL+c>J-Ca>&OqtCa+gQEVseOo<<`fDE5uEi^R)p(!pd=HBHA1s0<_#g4%B!PeK ziX&Uv9p49h+dU}if6CY9LDXNTg5>yUhj!cj%(v5nh%b1itjZ?%U+`ThZe#9JyVrc( zVmVGnq)jii|LW@%mn!Ih{U)IAN{D5mSG?vyQLR_}6(9~G}{kY%lbUD^Q=X5l()UkK=9qMD({#Qs2^c2Hcapy9x<_=LD$)%+-GenQ;D zVtCm86rgLw6`Li_TLB#wcPi*1K-Y?&GIUTp6&TR27qN4x=0WiSpd+G`h4QfdI!1d` z{8T}20=h+9bDqR$2b;9diA5~1hwUVw+r)1aG!4+_#Yb^WCV80?9MQfg9#qf*KzE2& z6|^vTh4v*e{Q|1_m{=Tq)AuE@grUm;9YEQgEa;buRVe$inA9q9ZVrAz`?7d#J3%Aj zyx^y_yTqLxvg|_i@D;I!#r|@U4Sr6$S8U73vZ3IxxKF&Qpv!}IX!nT+c@bPLJ_+c4 zv0=BYc`Kl=iUvADV+;=j7mBZmR~Q-*j|cD8z9v@p$+8zw^8xXi2Q9?k5}KEnWv`>Z z2gL>j{de$w?Ll!rLx+VCdJxc82B_v?`1>BwzAkJ!N~6CCp(nJ5#V!TS2#sjp7Ulb7 zSzYKLzKFGLzl2T;{YZO6+^L`?fF2c#E|z6Yp)0h<#JoX*4vTf6p8;C_K7tO4ZJ}4R z?~4`hC+H<#Uudy-N=&+x%Xoi(N;EKZxqS=zdrEAO5U=p3#10R731ycu^oaN(uskj9 zmu2GKkWYVF+;$n^yj(mQG6BUtB%vRNE)_o%*DxgK{TcB^h9oV|hy_;^Xn95~XXtXg zy;Y_^Bl;BNgok0*-=Lt1a0SYKAR(sn8Szbqq{Z?KA@ua83z5aL11A7kMi$Ft{l^|e z7Rz%AlKS&!UfHY0$@(umDC(cBAM+s6pT8Q_?$=(~tHwh8w;mMrpQ*p(LDU~Tfhy4X zA6^;J`KkvIo&V`U)b2F}NjhKm%BbBRJ&4-<$%ClfU&PPZq@Z?-;k)^@gv3K}g7z(< z%5K@Pgv6TE_oIImF*s@$hhs5KG$Pi;uZ>vDz|*Z*%rCA+Y>MlBboN~tCLiE@#6Gbu ztRekgPT#;WmC8CkaSNwEk605w1~$S;rFU`uLmdC0DE@7TYRWpr`Nip{8QV{})l{A8 zKYv_W7q1`(es<1(o#RHtn)oY^3+6j$a3VC)DV#nDu_kIbEpsI0Zy$GPgy#ro@QK;n z_Ee4=IbL;w_@Av`JYLzBVvWbBj~ZifO-TvG?^IJ#PVqa{B(7>F>`{)I;&;MR;LLb6 zH!y}Rh+X-Svv9tb19{^#KJSD&6l>x_FFm?d@eJ@Wm>ix zKVRY;i&+!0-z&%M*DXDsp0WA5_y{l<;*-bWIZ^(JDLGMJlFu@he7=RpejE4rc`vPt zFLI8o`9WT}_j1nH#>9^n;DF^AtY7f z=lhvLQ@q3&2(wQ}9rX(56t973$L2Utr`{7(1_ z`tyHQ^YalK=lD3hGx$K4xC>A47mKeVz7+Q*DE=PDPjmbn$1igHJC0xH_-`Ehe1Fgu z>H)-;3Wwtgj;A6%pw}aQ3HK!ke*pE#b3$jF`L)d)Uk1)Bd2f`+eH);|syDzsIxw>wNyi0CG}^LB!O{RMc4v?-IpR zHEMeba$XXRVou_){}gRO;(F9-5}{G8UDyf*rr_WtCN=!@Dl$xCr7=MUNrL9~4yIrk**jK0n_|AzP* z(SS}oar6sPPe*SSyAfCDt%09JuM_#yi&014m-=0FIz|N9*6&UIH*y|Hz3IEz_p?-4 z$<4lBA$^+uzfu#Cekd`u3-y7GmhN#9+5K}n1L z?N~=in?6+jrf&~=zZA3`Mfzsn=Q;jz`5>^ZjSs^gNwfv{{1^~)ZrrcxKa?1Zb?J+P z2V+<23xj7k2lZ@4bv(e9{LS3zX8l0LocPVYYbur_|N4rq`0e@~6|4Ps>2;wUSQn31 zWaGE9JVfDHU!&uQjC(tAm`t6B9gfR5uHbkD;wWxsb)n{G#TAHu0DpTe?ryC~)QV~1 zxA9us=URqzLR^9LMDY~jH0RId_;k)$CVr3nvpMH{j&U0pt@5G<@t|0k__g?>-fe!y zce?Sc|JNK((A9m zQ>9|v*lI1|^b(X-+S?JoiJ0mPt5`R_7q|)e2ZJ|p&No%88|y+ZaQX$5R^S$*Zu}N8 z<5#h6+>a}04`TnABCgTz)*scM*L}um#t!2W<1*t)<3{5a<96c#<3;05W19a||2F@n z{s;We`H%U3?SIAppZ@>lKiRy%++kiCy)t?*dQ0@a=qV*lCA&-Zl z?D^QsvA1HAoCVHOC*$mKKI(kJIpW;v-0eK=Jny{Z{Fn2F6OEr1KRezQ-y45l`~z_f zd#a8-&4jch_(|{qy&ETtCk={!Y=_DyS5g3a3F=6I0g89@D<~0(~ux~DlrQ&>~?zAhQEqXg7j?E^$EN_ zj&waJ^5H2~0_nN%n)~2+EkpWCxV?C-{&D{n^R?)9oS0V#W0-7%;(sRrz~p%UeBw)7 zVRRnd>N~#PU;M}Cz3f|KAD`zFz0UD@mibEJ_&lHZR+922f*X@Cswud8(JI=FslF0C zamK$zYqOmL-I>K=S$9{aw|{dcw>Ohp)74(v+1)Lc$;{)+ke}`C&2;p4WqZZ?UfE`O zSH2^QwwX?`%uS1BvP?8BJ2%sw2kx$pj3`cT&h&Pko!P%)FZy1d>CWtI>(7W)nf?vA z?2fMP%<{JWHZPm%j+bAkzNRZ*z*1CIaMNAc{;Y>=14BShy>0I5&#a{GTnd)97{pDAZ12u>13m4T9Qxkd)rl6H zGWou2Z$7iEt-HIut>Z$mx~;dfJF_XXXCRaB2lEP?T(+yNcPF?<4DF?#O_`2N*Iwjo zcB}V*#kuaTcCmSXzCY6=*0=A*EQqxO-Thr1ZAD{0r>%P+vt@r@Ml@kA`m*`9_U?@6 z%&Oi*hnzp)&JFbT;sS_hAK0-26QAkb*}qGnuidgMmuc&yQkfDREF%h#G}Nxk^oynq zD=;+(OHT73>(76klO;YTe~^iabcz( z4Cv@n`hb{M~+t8M4>&c5{kf#2OM1fodOASFVhCpPA(rki56LDo`yJ z4<@mq71g@F*R4WK=k;7m9p%7i`Vj@x65ib3mh1PrBOIIi@wa7NEMi4>TVFoY$*Qz5 zhbvv{d%fD6Ss=>ok9ZG_j4dG34dG{CbryPQ7e!lhU7{U|&>dMGY6;_(xM0?14M#q@6KY=dPoA+R*z`v z?ab_>4ecz5Dil6a%ksrZ-qGBmrk$U0Y8^@Xo=zTL%`&exW*S z>J&}+6`fuEyqiewkbo?hCx<45czLevB9czIdn(CRnYEPZ6|T(YdfIrhWL*r66Wo1I z+dj1$_2sZ0@=G(_*^B1X)zt~o>#8W**V@$6*WK08)i02Sq;|2UqG z-k)oe1`9w^B3>Eqo_*c>sot8*j{eQNx_0ynjtQjfOit04o*c6?JU=4PZy@YhBvae-SpVM%W$&Xnl@= z75h562lB8*0IqG@C)RfLipF**s;s;|ip1*7K9vT_4fxyCOWSg}On?8TOy_{)`>Kvk z47Ya^44`ZeI?Kbd>R*-}zznU-kRYt->hJH)Y$3a7Q(Jpi@7gX{2swr~XS=g|+xDXe z>@1mH&Ra78wTm1WUE{&9()wus&O>U_GL^)LuoXZv^NJ#7=CO|ZLB7}u+l~{P_dx4Qk}${EgfpWdMGmwztg(z}%`@Sf zuuj^E6)fYp!`IW*n}OLwI~zn-3K5nC?Kc9u4`k@6Ysd;ckTBsfQKCuo~#8z--?i@}c#lKQ`U@rB*-0k#iS>f%MO&bL7cCO8oXXB4l z$okyYO>4-0BYUZ{U@$3lfL*X3vr&tlGP!J@q6u5pK!0ODZX~zE+;h!9v6qZlWqT_7 zk}V3Ag`J#DY{5z>D^22_O#iNIr=ZQOmo!?3Ykz|z+V{Z{-oL#a(%s}nZOgRr^2VPX z$YDY=m?l1!xW7<{eXOi^K-+RZT|GO+4yo24QaM=9`$ShSQ`XfBrG?q9N0@{6T%lzk zf6DL{S%Ho=4rKf36h`SynVz;T=<}S&?CTS~Vjo#_`TjPP=4dtm?Z65rLF?bul_ykf zqFwaRaSjU_QiY=kzLl_1TnH}+hAo+N+ytBhsfH>bmAs`b2T5BAQ!NA5Tv(U~w@GG) zGT31??VVmvf+BpFEMZe<}_w=>(?jKtKfhA2c zwqRMdZ-0&y^w^>;m;kV`crY%F%OC{x>xLQxd(tQzR*EI@8k#j~*mw4078 zbT`1Rww=9@#;%S$4BYmCojXY<6>!Kr%mb7SsTaAIy6c4Y7$DDi3q@uy4>x7H+xBrP zUqGiCQZ*E{chL@1C?yr9&UDgZSql-MlhF!Vk2nlvU=OU=2mN*y4s`-+Lu~HOWcug~ zgrx`lwY)cvqY*7HG{GOUr+v%=NMWh<#72!uuWak-!Zuq}s&cTsWaJ44#|@G_Xmv7Y zfK;V6;T$R&bGbI08Zh1BT%2MuVkHE97vpQ9(=b*H91xA}nS?eL-eE{})3CN=rHX^X zAT3ICxQYux2~Cxec-N2)Cd+OexeL%G4j=MtB?+R%0=npj_U^{+omr5xtA`Y29~2j# zSk{7=9Bo)MkS$qByPDNy*<406X7b*VYkv>)6%N1!RMb7GZCAB7og>G24qPdGc7tg5 z=1J42W0X1|(dm}URnNr$NtWap?<9DW1O5n*!DB@S@_eQaSU{wxZCYPT1A_)(qhZx~ zU41U{LN?i9wj+_HFEyBCL+WgjF5j-Q7Zg#expez;51!MMHhj zN?|*j05xnfc3^!$t9Rzbik?0gjB<@w+<00{;!NJ~h9TaM{Y^K$tik7n5h;zp4qG%_8 z#l+`J@VJjXMdQ^cA6Rdun@mGV0aVABb`sCpOn+M^P6A6ayV~}4L0sL875m8Jg!N9` z9h12si_^k>rKP!w%&DKxLmFL7gCu@{pHgz52W9WXEpigNaPdH?-(nc+IMcawKg~$N z=><1elfvbVfEv1hw*?fMj3ZkN1PuNtIS8#nF%#Fr&@-so^Xk#j;7unS+R({i&7Vn<-kmkXI!}8h$Ec4xot0>BlxJx zTMPMoRu1%bY@g%mTx>ympp6FL2ja7KQz4DnUfGq)_pi?_&+KR;Tb3}B=|KkQihW=k z>*-Ay=u8-gTe54i7tyAk<$Vw^$?bx9U;-_1(h*}alzvyN-GZ5_-IUom(A}29;!+zy z9{cT1cpKKTeq5Ey4)if4n+G~N$X&`g1tFE=r&@3Xw)K(i#aXahVce_3MESQ+D8YuEjYe$3+M>&3mz_Tr?P#9g^`Ne|^ z<}906Uw_*Cngw+$=GM$Rb?Ne&#>To8HOuEUE}gev#cA{AtXMiET3N`jCzI9D1oMbw zkrdq-^>gayi0RX@W#foZw{HP_5_O$(YU*7@ERTBNkJQU6yE5d(B)30KpV$%k5T^_R zo&@%DVu+0xD5P&Q92(H-8TjMLymvhX%iJZ8(=i>P<&y@rIY9q`QF2=l6W8JUcvW~V zwGQ9U*o4~+8^jiTL1R5&QL;sJ;cFT2Hi!YdB_^DefO`@0cs~n|2=I#MF68%%KKw1P z+4!#;H9K&$=tg-KwfgCAgz2-<@*J;Z0H>1-UWn~Sj2qWzML2rsjngv1-pTp3h1|+Q z&E3Gg7a@;ca-gFRErqokF!fQW*MXcoJ^&zpQI?=_z`+mPv(c&-DUp(;+jxw!EKl#} z2B_{%!srwJne-RXQ=MqrkFc<)F7AZ7U63ohhPT<=IY(40UcvFSBr137syjJ0va24v1TvxGVRN?vX0(`)v5$_o;!`p=`@D|}J ze4oBaoP|3HYs6Zty!Ct*--IvNY{6H|&cRo-nz1r*eO|9as1ZILZ-V%n>HW?6v2sG| zs*gvQLBDtufu4!tZp;Km*t8CG_Are(F4=(?o&((F8Nf&=MYOgfE!!>zM5|{Xs3VL! zk-v*DoqZN^N&2X66O*wYMN>5X1olcLNlZI!5{W0i%<4ByEJnWz-(yvs#@8UsKsW`V1{iDurBSO&_r+`M zs8J;*`_XK&f3hD~=qHMX_}g(J>Ie2o;dLWA-oMr-#9gUi( z6pz{TGbw%s^*}>wL|B0^9ajkA)A7ErFFqY$HG$O(Rs)2>F}|&Xw9RqA z7Fv8Y{by2Ue6=NEydtjIlLIzDE;lg#N%*21*Wv0IGpZ9kh#*NeM#YGN7$_%z6I9#r z4b+&(Kn0K<1Wuc3*a8)8loLZ%%X+>*L>QCZ_VLv*VHQECg{j+sz#Xq4#;=JQ)et@8 zZ3XfGLYSEeab{M71C#whk~;h%3&emLnhXsPnr(^KL#dsLMO&vry)f>_jaNtrt{Bb1 zH@W7cVEkX>3S2wEWci%oL%QYD)Viab`0!`JMBk*CW(c2eQrPlqnl?$UOPZ5}uq*>h zbdpAFicjT7n?i<3peQV z$E~2V3)QJP1+*aYqNatuzp7!tw%@{9*U(3l`yhf*Ops<+S`-mF4+}q0V^hF4V+`sY z75st-3t;w#e@hu5(j`p*oZh%&_af(QwWk3)amC6DezQ zdqP7^%=dH0i4ylXH{(&Xon*Mu7xeQ)6jdy-1_z%a~tL_ zXzQH2U|weK{HS}HmR%87w?spDqQ51BLlMqKsoC^U8SVLT{+SnM_Mb6`XlVGmqsC-x zSikw*GpH~R3SK{Y9y9!lQ6qU*&Cb->IMl0goY^PG)6{v!pqCsP{{FjnbR|WjqXz`T zkBu73yG!PRQs(F};4r?>_-@q)Vi=#5e76!GoxM9hd(eFd`z~J_9r;mXdHUTuEy>w5 zmM*$QJ8DSpYSo1&{6(S$`%c3ji`AWZI2yqu#9;;|9W0CTjGDEf&fC0PO4sgSOmuq7{I4mh_Hc%st zlLRv12q0QCZK_p)v)klAfScK&5YnMgNFKXT(bmFN05zx|bQC5UxjmzmBO{u4l(5*5 zq{&=O7C-o_!3Hg{0yxF5W}4%xVZ7oD2*cliOF@fUVZw(pqB=kXPQYK0qH$B;zQ83r z#I-^+O!*(ifm4PZpkJb0OIqkdHrZe^Q8m@3E3W{K06n4iZ^JC4O<(q0+jN9ZYuLBrcNUk#!IIm%$uL)G2oYM03$F#$oFF!&=A}Wq5<{8-BIH* z9F~xQ3i3Z3P>`#e&OR(CI(a!GPp~*Y9Szc<)wgc1s+v<*|Npjg^(+kpL39(8G!|lE6(oh0 z2^YP@iwFk2K#CZ}XcRdR6HO3;N+Q_W*@%pTh=5z zj6(qxitDclWO_tH_@W}AC2CB*Z-S%i*b<&U*#AORuzmU9xFNJ^{vjjzM1ojQ7+tw% zoHt6X6zsxX_^f&V^p-vyY+h`JQdtJ4lxLi^2Cywhw#7Nsy(6dd<>dJE>}g{gmm^zZ z{3Ef$of0kbN6Pt&yU=UaBW~MUyY$fMenc(Q?OJUSy9SiReeCW^Ob$msCctOdJHKE5 zjRlyqP$Bo3I_c)ZheE+6*4t0IEY6LVQY}6Z?a~S|T}BaJ{w-WHK;H^&E#p_8UuRk!vq!p8$e&?7wpj6knY9oH2y+43xdjM&wfGt{@VMW zgTxZX4ZL$)K1HEuV2s!TOWfmz)N+|^k(v@;sN+uDDvv91%PFtzfCQfgGhM6WQZIQNs8b8u_5VkC)H#xGXa9#f JeJy@wflrjlUtItI literal 43008 zcmeIb34C0|l`mX(>AUnI_3f6s z)k3V-3{iXeC${*ly)5+E5iKIb`;lVF)X#htzZt+Y03qW1tV_Bnf#{cinh;2*KSQjz zo{G}{oj1%+TD4r3*smON_Ut1Ax9LgOW zLj2kL5Fn5Hs^~_H|1v^c(O4>%dJ$vVp1}ik^Z`J{-wF&@V=32PL_wleybK^*e+Q`e zTOq{CiYPz6pZJPDqD>be@y#2A=r~&laPckuC7U#+0rfqhkAMm@oE6prqsbHng;CE? zk4MoHQ!gik2#~u%WfMPCSx=8*R8THS<&f<^LOe`eA0Z^S%m=-r7-Zzt zpxBfe!fK7WND&K!NH!VbI<&25BJ5$S;h@l~%+VOtstS!(@vk*nO~1ydO+V%+M$ptp z2v4Z!kt~87CT=8zw3_2u>bM3}3n`t+)Q?-JYL%yejB<)drh+;bFQyR(84IR2>0%5I z=pXTj5CTusY1r>~J{8tSh$r)62~l6m)$|eSd~qsAj>Rom!*=VZQOb8kDx!}NPv#}f zgcj7H6u*vV%Q}u{`jx~24MMGpT9IjyvqTpciP`<23x7$_xd^|KZzxfAul8BZj{@hM=go)E_9GEkKe=IA;6TQk~tc?Wy-LzQ9b6Sz{xIT6z zIE0x90Bcl<(@?V>{IZ1Kgg6!rh*Fq|6Ai#jRaL!Kh)}lPCwOA3Z%FM6L@M%$CB$5@^?T170LUUa0jBWD28x zHsTR`VXa+6f5Hpn^7qz!>bS1DN~Ih22|pvvlaUjvRbuL{Xc`P&EmS;drIL2`bkFka zyJEsE&H?7y@oKhkQ9e6Gco>eP?b)7nYyP;&D8CG%vO2IG3qjdnbdFiVbhcpLSxGZ1 zJQJcQXfB~G@zH+}p@oR*c>d&PSS&;Y`fn9w^IwH973YEq;8S={)?mIORBBNQ+5(b$ zV(pZa2uZ%0Vje~lGDtdwR2IwX!bC-+I1g=QwUkIYp3`6}Ijt;!&V`|SsCp5z)uMu} zW7JeCA}}XN$)=>%EuN0D5pm3(FTVE(NDwqV@jv4ZwcLdyn>BM(R&(t7dg`j~)I-@q zm2xXi5gOZy>25tVu_Y`w<=&bvooV#t;w3YCKX4+%3lo`??48Q>kJD z3PC8DQJ4P-CX_#tkhO8DY=t`8Ns|R+s~(Jy3dB0X*y~TqnUFwQvUnYF3A!-AB8mL2 zkG7JYhIbS3G%Skvpxao4z)NjCar9zQTNF0QkS=~L=A<+X2(XDp?X=DES%`0m4~=Oo zXS%poTk~TneY&_&yDp}4`RPp|aXk(BL|tF4jgYce8Xqz0?*zSnqVz>{RYwYh%vMQ7 ztf*Er70WIW&aHX3GiiEI#!&SpYlWoixun!6A!*u}i6A>N9 zNiTC@FA)k->%k}J3=55U5I-u(lc@vEk=B7U5&lnjmYhFc$nh*Wc@n|2fiYq6!ig1i zghWHmD$sDe@zq9mjEE{RfUx&^#;!^#leTwjOj z;7fpqOtBO2P?Ax6&zs;m!3KpbBW+MW9omih4-U%o0|FKwq!@;uY;P3CCK;eq6O1%q zQ)~cT^cPsE#weKrM!E`At&}Bk`=b>18~wFgZM>EIwi$m zB+5)6HQRmy7xiqjOtFergBq+aZ%!u7E!tCnR)HCVHguyNCa_fxk+68Xb8`MP%7=jv ze1wMjbZIVr-Ua#S~u^_<*C&-T0RfH2u_&l*p& z{4~-i%pS)J`Dr99D$P`B!gCk2y@%Fq?B4;jZ+j;I{Nq1Lp9gNQ!*2n=Sz*B(toRI!Cqut4T>9b zMGae!FuAsKb`7$-kgX(<(&h+b8n3<)Wo;U>oRlr+fP>=jN00>9O_ghLfTkAdb#b0W zF=LvWs*B4yMqQ0WcPc4#i)%=Xth(AxWjGjhwJ-r_;g={Ns*sU3lv1Knyny7zmQ&+p&v1ha`dfgqli1nfJyS0=&?6SeaUWl36xrlxn?*n7D7Z=nSB8Gd8-a23Gt=Zq zl8c+Ek1~A@H}sAVtSD}wM6sY%WfZqke8EmXx{d2d>kc9kCXRCa!Mj5poJ~I? z6jA;^vSAE?K9a8WL~U)ISKf|VVJltS!IX{=Z|ZmAIZ_W=uPzq##m<6Q#(t@o z<+w#C`|y0L*ohzMb2G&*s5a2yiJEYE7t$l;OQ>opW*0A|VlCf8kU#U4CMgR_@XX#;byn3&Or475rd zA+<$C7Spm$RqJ64Vadi?xSJlZi=$$dc%k6HMGJ&m#XW>c97|zq=3}yhRPI^^wHH>| z#l0wL)b4_=V8aG&w(8iWD_L`yh^ewMeT1a-nmlUAma?#rhzfm#WVa$?0dyl4G$Ce* zXMZSCvxqwu|uh{FIPu>cA)*eyW35gCOLLi(>n`=i(f znR@1D26SXU#nFVB3THiigr2P801}}$JHi$hI!>F0ANjs+k}ZwKUmu~?;Hh0nW-zy` z2AYT|7YH+E5&Y=KEworEy>lsfgu*~<;m17JMvTOfy0GTiu;j&%No!QN#ukQ60B6QO!cq{ryY8>o;JUQt>JjiddMjG_ZUm5k(LD?mHF! zChm$;JV*@%4kw^%fcwpNIAM%{)hc866D~v4!ZE7|!GWRd6rrua969iog0Q+d!% zrnAApdNIPyDJfyPzJBYNMIl0AE{A~G%NmRn~gvU!5L8@}bnB*<0psIuR zAC?El5|i=|e#5p44^7apO_KvI7u|ELdaQC*(zQI7-Bigiv|l*oh5g-t;}3>8AB!~T zl(Uo2xBdifb9oj+o}rraC4Vsn+SG-b3BIv@flR9X<_M_|vk2L>jN&^G@}~24?8nbU zM&P5UTXf4h)Rl?p(I(_c9bt;!0~get_eNEWFy=H>V&4#B9-*i)rO-8SuThujjcfWm zPD*!3>_%!|BSxJ{)h&`b7nr3&b6D8foUd=Sl(u6!dt zya^Zj{v0kq34iVlI*#nhj#m&a9^=-D1KW8v)wv+FRvZ4 z8D2cT55XYZp8_+m+MURc^u992%L3d7|>WdGMSErJ@ZTXtM0hXb3!n0$3j@aJaFz(X5n@2bd-Qfg;i7_%~K zXRf{d4ncTKbvP3#JwHC)lMn+7ZAh8W4P zqWpWhj8@3CCCIY^tMSBf)UlPQ?d6hqn%afsm6ye;iSt+r24*lFwqXH{l(4x|lX3!u zyfcZUqS-T{&S*wEhCQ|ONL_7@Vb|g}-qT^&>CPjw==Vs+y~3W>8FA7bQCsfEf%{9A zJi5c9>a1)%-HF}Oz1dBcJfcJPw24z6*|U0#G_YnDSW{W{P^j*tLLdUAh=N)w8+5gk z*`OM0KB4WS=(uvmeMRa_OLU)tr>5el`KJ7AikRRSb5$WfC1=fa=YJ`_NWrZ@+3h^>$(SR037 z-;g$t3ctybzgd+km{X~JBukC{96ef)>wt5#&|yQJU?q=Oa{9WwwhNk~j^%3^*wPJO zfajsHS|-ub&hrD>oAT;}tSxixfqSiqRzbGPPmps?mPE_I)v%Ir@)nY7-7mqlC*|Wu4VuF~23k`pM zx1*xe9w_b!eW!~VZ$*aApG1Z_?atT)@o|;W#w-Y>_eHWWeIkt_SCr^;4#y_92lgiVtAWyR^<%z`U%!%UEd4f0*r?_`| zN{Q9N6NKusCkd793)TOnX|?dr?>7Xh_auR$J#&{X1e|pq1QuF06;)zljoatEkBW+P zM6X|k*%pUM$g_KrB2hyYfsFdMDOlCTX#3bgCc8q9nU9%9la01@p_UtvliJ6Q0?)*8 z{JQaSO67Uh(ZViQsudgR&kJ=V9Y5|lJjXq!F4ITbY3WChw}D_fla|G3QBxnpMw=v; zo|CG&(!fADa4$Bh@IgRxN!=`KwXT5;DUQYFixRF%_)2g^k;AplGBb zsdANWm8w)0g({UqsOY#VB?4cRc_%Qs^*zK#+i6r)RW`Ge?Q*KRS161XTy~S;?2t$& zT?|HcCJHDW?GJ;IO1eS+eS*$3J(oRjg!Rjw>lY3YHn=e=IAS}Bv0<0R00p>|@Ng<2 z?^rqF!maX-l@OPUFU{3raEvT&hCZm1@WR5v#@j)`}b!cA#4;N%M z6V`9dN3teNRp|WYu#SgdH6lOED@HVXP&k&{4^WEkgj4%s#DWDvha48Hy7Rkw$e?$x zz?Cxoo`=6){;OzPh!iph@&ztzfjiQ@Ms8 zWKeD_3d?EDgjF64a%kJmh4k!_iA(uyUNK_XUg4@yp%hoR;kt~~86h=5 z6|vsK?D0Z!eELY$dgc}I!cmgVLuTUHvuMtSs61x29A(1ytZQ}ROj}*>YIye>5#vDN z;K*6p7FVJlaQg-00{%^rEP_9fCX9V_H;=JR>l^khKlGXL7upG^`V~u_@RLkWgU*Dv z3+=KFNiUAe=2A*g^2{dtD#{u)8EW}CC{>f?jfv!C>gBW)dRng4yf0vI_H{)4xYVIg zp}jGw1i`+2jkMuc4k5<#%n4#CYX?#))eX@ZDSa}~m2Z(n+~A9W`2+h}XWJXB0-ucH zU%@hzw>HT3*7+iFWgeuQvq?Vtz^yZ=p1MB+_M0%Rw;Dq>xj!Y>)f}RoGi5FXUo&bY zvX3e$ILaGq%1+5?;ja{^^o=wRDD4BtDeW?y@^A$ng$h~?@jsCdUBK(EWT~&_7p6{H zU(pd7f3#qyqAmB+!1EybRT`2fRZ-_~>(G}bV8A>4GX@2gGLdbJHN(~WA}E>%j+vya~E-=6m6nah0-*Bt6sfV}wz z9^mh?;+id+>r6TjouqpL358_1GNrcjXdxL<1a>5&UX;mC##+wDRE4V@+qJq(4}L*@ zp(9!4Re9k{lhyQdc`}|#df7{1vv^+hY!oLJi^i#5wHMjt#brHeq2oBoAloU_JKS%q zPVegkmbeGsW88}em5=jnVk!i42b0wEP?5WOXDXS1|1nKZoWdYqz4pJcKoi_4Iz#TujjTq;r{yc#dbBEWTzc}cHEW=)}%X318( zDLj)UgC=kFpP)|X@yS^Az`evL9DdRYNtaM)fdgf&kKrJ~^rWGbN~TP?h;$~?*{P<~ z_bJOuqf2R2OnWJyOL=LvU{cp!%EtYIse4s^innl-`{QhtIl+8Y4K&xtN`8C6Do>SO zl&Rpa&tlt@PJG;p4b=yR4(QD$LyAhrOMyyBUn=CA?u71p*|=Y5G76zgX&wCyBm_3) z_`IP_O}0kX#OXAxea_K}9V%H1Kfpb7+9W7TJv5=Kk_cGp5{HUTG-zIwBA+^1i23I>!OV0oOZwJUq-T3Z($gu4fh0;1P=9lKbt)JsB6Zq9%jEU0vQzI^DDM8Vz?kIceiOA zAj;8nD)zu^dExaIE~BMU+^8q5O_EJ{cmo0!YddO^9I1C&xRP#Ic0Eq^Es+iL^9Fi` zK2|lumfS3bvLWBnAvu1O6y10qq@fq#PMq8WI<&yf-S0tck`7Q2$EUx7cuL3hc?jIf ziNrI`$%*GpAmxW`NxPX15eD>%_X2l?@My;mEI@X zeo>3xdaI@+RfZ`Uyz@i0$$y^CEB=en+5P_ko%A-J5DpC#~ls!iNudP@w z7Ezv2yC`hb%?-|YSf@owKcP*`b>xCB)#+j|T-t#!qC=NBClSF_rU+;Uhe?SBUNGtL zPnv4)X2^4cq~%C;u{bV~P1x*_GK`cirsm}Ri0oxBm#_=Q+R6IFlPf~%XkA!ZHB=)V zq}~kcQ?u)@2knvUEL^W94a%V+Kc_5Ql7Sepg z9Hv`N)L5l#NoS!_uV(#b2v8&)6cr4E?&w*Vqe;v5yS{|flxirCE_oNqx`VrT$#4JZO)2+V*KVg`M zJ-FOrPe_f((`I-UWb zU*ez#ekRFdhc`gkS&G9U#Vr#irS$9arpQwsUr>UrLBrRvg&|x{rDv85Ys$1;X|lQ@ z<}faUV^y}2Hr6}5zL?E;l9}X*V!?q&@r1UJLD*GeU!fPpIKh_90Rd(E?O{tM8>+RAi;}C_i2oL@e#ER^`elAs27rhcBbt` zv7qyIjhcNQN6D0;SOuzxG>6$CulOW8)_N|a#|uj{He2n5Cs^#Dg;<(y#w{*Mrb-w$ z+Nq)E!JM$%kwJ@b!3lGi%G4{(jcq9xu+#T?Rj_>7en$N&zK?>fSQeAc43L@i7m<_@ zhM##(vKkUxO}42nZUKX_aU?(ANqUBStFE--!dYEc`{)TYaS>_8MY6gPv7^~4yjp2n ztd_z~M4iT^n`TNW!*rK|Ili_iHBP9Wb=ZLmnn*X(g|)L;Urz7ET3FXbid8y_;UB`C zRsUpzszyrh3zR2pIJ~Y*{c%jXU1Z7q75uyGFa9xqmY%0_@d7&=$S&OW?O)?Qh2K^k9Xmq(%mdgw}>G#vW{=jxD{EGq? zk35`P`qymaoK>sVsqUU|r(cvE_7}LLVQxKAmx*R^!w?$FPWRzxHP!4`cHo*Jj{Fe2 zR2JXP={-2iR|7=j^DM?^*(qcv=EWw+jv9U0Gs?VJIet?|7X}jHF90~Yry^KoqAgdT z5np0z8-t?qo(@l0E}BNsr6?MdQ3WZ>GnrEC?lMAA)oaVx!8S!2AW(SjBbYNYAq zT;8V9Q17FXekL^r6*tziLaNiTWo@ubW*8BZ#L@l3SLMk8-L zo?JAIqW>}Jcm|lhP2*WPgz&83p!`DEC%hImsf%*%QP1QPCaMVojTslq&cqT7qgdwZ4l<0$Qe_+UsIG2fC>l(f~FC?yBSnDQ+#a66K{lzEP^ERLayXJ5H1 zPtHaX9>Vog=;|mkS$d%CX@b!>(^$r6EPVqUQzDQbstEbPA{HURrs$oxFf0X#Rs^1= zs4UlpKoGbjGyiWP*Jv3XU@59jVM(Y~)!@<`mpkBRJ4`jne$OT>8a6wV{njn8I-bqK z{aMY{h}8PYYIrfRzIs?~Y|q2pN0vlF^|TjfVj#^4638%$L6k`#k=^=vcnvY|5XgkI zui&r8AfIyznM6lVEt8b_CNfDyz?N9c0g@!u`N?$*7fqw+MJO7S4RlO^X(3^nsAJ?^ zQS!mY+_V%RQ%VdO)h#~-KGrfF2%T&Um(a&hmIVg-gan4L{|wK_s?;`68KiC8Q)nBi z1!hNDY`(!8_tCjhAn{I6<OTXA&dtL1&j z1TV-DZ!lYE<((qeyc(|tt;BHS0c&c?s>f~nuqvs14Lsqf7-TZp@*4D{Q&)q-ec~l0 zFAxU34uj1Ytb1wx%d;K70M~m8^*{rmuie*S?+V*Fx-o@=RXToVOsyTn{(V+wZEw;t z#XXqCP^5GO5Wx?`g*7P^ z{Yu`0_%Z@#CRmUDwwx1gv!2+8N4Y?#w5-7m<6%giyB@m zRllEDBQ;v;E~V3AUNxTOYPxU^jzs*7BtOdxa0UMdT9$|lkzxZxTF5>Y&{~w*ONS~r zX-VHjz#0!N7io+808(T|?Oka;mtv#BU^AF9-?(8$kI5QG3$3iCv+37+Q#%H8v2JLoOrfR6m53t=*S zz>e2SjerThT3myDuxY=C6%nqS@`i_4LylHGyVP=cC}M7LHwcwO&Us`UnOWEhbd`m4us*mYd-9jH* zctZ`w*qk(qK0N9A6kvKMvPmDFl3i3%&$dj;F76N5Ro#Nipt$likzdrYhSE%NQ?v(D^xu5@nIe6U#0{ zdbHByK@Xs%NO9p+yDBeK;Z687l#{CLs)d9sJ+%oZS+4>!<=qTLPT&tV1e~H`1<6-x zADoaj5Y2*$-gwOwXokGk8(J$JtcpKVjJYQxuE={-=!=n~@;4bqUM^$2WzV z@HG?P2C1e;sY)uhm(;;XsoC(4AWq#?a#m3N3FZP-4|}d!=20YYl+*d~*%&X#8P>^q zQqEy(DqauUQlf5O;w;eBsXJya>|xVW=` z+ks!d8wKKTQef7blcc35NgJ<8 ziyDx-)6g3Te9*&pSKI}a^Awva=;-Nv><|5VByE#}QXLXmFIUV`bzRmfNZRpw0Olwb zAZ1JY`|DBg^a3AeMPcGG&AMJej@O`}DNeWV=&Wqam3~e&V$Jy80f|R2fWB}-zZ1?A zyq9$Ekafnt;CF4MjPU+iE(un;5Bitx1@?ul>3tE4s8SmTlitZEf=Mwt8DJTUWn&`k z5N~26S+FmpZ=P<5g|hoac6(rngesWkcC)`0Q`6+tUH8w88TE9fWW7nM$ct?iblfND zAlFjmWnd!lFitc4%h$A*G%z=CIO?Av!9^~Oq;VHH7>5bfaJHDr+734(mF}|A(#Q$1 zZhye4m733w;=_U;1UuMI6;UdwCn}GKob_*r)~!lcME+vEK*uWnu<*lQ+ix@GDw$ww301qyC|6g zJ+B_Hdg7xa<9Ck0Ec#@WXt{(!=oi;A zq!cM>;?+WC#-P&t(p4sJAxX>O@QiCzY#{?;*^9$ekWab>Wfj_xj{pg>x~gNUZ=HIU z%UDsKY^Fbhyksck$~r#s7#$6dZ){aBq-%+YiVMSU737J@>4P5vm-qeIN{l-Sk6#A7 z8-oGOcL?bUA*(;i-H+VAocP!{RgmI8lU1}k>A?`HUh{N{~DcT>9Ejs^V)4^3{C28UiN4DxrbkTwS&H; zLhrcJyLj{-2i+~_Z(w5j()l#`P|06KHW}%A{(jpg{B8qu0=fY?z#hPrfB^vJrNFs| zcst-mz)gUofcFCK0ek>J>g5r@V}Qp2p9Opl@I}CLfNuc45BL$_CxD*=ehGLL@CSf~ z2}K|LiUFztQvmesx9Na+fW-i^9hL#k1Cal93xMY6WdM4YdJmuo7zT_0t_55VxCL+o za3|mcfCm8|1$+$fNx-K8p94G(coFawz&8Nj2mBQ9uYg|zegk+N;9?LWfSG_ffCj)~ zz%sx&fHuHIfGq&rlM$T&dY>%^z|9VECEzN+VZhq~e+{?=@NU3S!2N&+0UrX;y@IC! zUj%#w@NK~N06zl!6!1#`>B-*#Gy`%0NCIX8&H!WqO95vC&H<5$qR{?GU+y;0r;C{fvfJXq20iFar2lz7JYk+S9z7O~b;8noC1O5Pb9blW_7oZw2 z6)+tz4{$o50dPK`9k3d(4zLNZ18^Cj7mx>B3pfn83Gi;fJ%A4Y9tM02@HF6afad@& z0=@$H7T^bfe+9e__!Gbgffhgn-~pxp(tzoJ(*b7y&ID`$TnxAjkON!=I1IQA@NU3S zz@32m03QT=2=EBtF~Da5&jY>;_zK`_fNuf51NbT6*ML6&Yzwju@BnE*9bgUsekE}x z;5Hwz$&IYUoTm;wz*aFxAxERn47yy(3hX6ML$R4=|a3A1tz^4IU z06Y(P5%3j2A#)~X4}Xzq-dC4n0j-BN36GJ(4*O5}zIzNTfn^PUuKbqnPCY}H>ql`H zF8B_OSWucI6(7N(La-tuz%>Orh5z*Ww_&Zri=U2O|4uZAPpp%jDZkSMS%6cV%F&&> zui+Oi4YaS15URRa*EHj&J`V(=i-~|q(xFsMeLDLmMscajEJHiu+iUs=Rj8Xw-&3>b zhf5aZ+ zMBc=NRqJPyndjQ_STQ81|QM& zEY)l76o1jm|4tiDF?~creXEcVjeo1~Sc1P%$cg?p3Q>|jQ^<+qj8iuR={x2+Rzq)} z{6>|Iuj?&7>_5L>Bp>si+r&G+?0>_sQGEPm|9Ou1`oGI(`o1TO@;P1u z+8_p$P6As~kDFEy-v$gb#fv439`cCV$~=nuc_he{c@$T9HFDb2jB;;lc!J=|NJK&X zZ8Z8aT+moPjCRIowxKgbR|a%#B)X=tGa!5oF1+9r@?BKPO4T31FZ(e4van%JRTlbX zylgG-!u^H*)}!mzfh)tO!Rp+E&#GO*Q>C%|Hz+^e@!&*3J$2Rea2Kny=&ADL5 zx>d+~7V-DE$XnS@-!0@nTFNiJ?}0PiFrvSox0pW8gfSA^0YFXXA>t0eQvj3|?*>Ex zaR8M={{kBkOAXtKluiILxDGuNFXbudimN?ra466`^#Y^Uw&9JBrQFu;>atA|H_j-hunC@ng@;Ubb z*AlZMcEl3vBdrK~IUM8gJ`SJY@M|3YfB{NZ~yM)7)oN@_=H$@LdZxZ)`8J76R z=trWK_+K1GV?>)5+lAI=A`FX-v1<`-|CVts!`^~okE_^U zbL zYt|y%k5CgM9A3xa?IzK7w@I{p7}BG`?tLEN_stg(UJ&|Mgxf-tE2*t)QT9vr@ruwd zQD!vsYlOFi{wTJLy%36Fr2i>23qz36Ptzc8Nb$tqJ5z8z^0-6oe#)7O=Vv(lJcqJh z&pEXyxx{UNjO}#KLN6}oaF2T>QvPT4b*3dY<1_9_?KN+;vpGW&cY`xeZw1c1GFH1- zUyj(1WemHhm52?^=91V;Eyq5029z}FiS-=2RK>RHn~?WajvW@4BhM9sb7je*elcQu z=TYo1c3I1@Q~n<+_AZXCB~eA*%?T9_Pkn4$O zjNRD9w_r`6-hLH%HKIes{u!|;;vmNki z9kFR*Jyvtdv(4M_J-!uKqp>HheRuVc3Bv(@hPVNAKBE3jIzxO(Yce0hOqY3I(zcpU zicAo@-24K*bg`bXP`$6g*YJXjiC>z_p#{F9Vp@n|__{UzZh+6}pAj44*kO?g(N_Y$ zs$$KdSMY}9TG$3C37m%3AigSN;s~%biG^5|2@BzD5^-LA4~zG5>|9(}r2ah=ifB#Z zA#!sd_CzSIHH#NGMmU$_9go+7*nDlV_~W@$lJc_J67eXxMmW}_EfrB(XgPM4c9!_& z`F?CSZr_sYQs$kjEfaUF^kePXIbv-)#cp?A4XxA86;}kYP10N@SbKqt%|qU5u?o&|D!B-GYs3o|%Gh#i zzqVHVmSac6Mb;thLh;l^GH(a+)(d*m22vn;k+)H7-yrh}z`0qxpkiZ)Z4s}*6r&c7 zSYz5&5r?rwv3n5PE*5g^OX5S;JG7nRZWa5uHHLo)=qXk5Gbnkn_**heQ13;=I>pUf zWb7rxE)nuyYrNh0C1RI}?{eM|q1(4;U7}_OmBg$;tXI@tEbGm&yR|*yyDD}jVtH{# zhs`JkM3~#iz7O?^GGZou`SW&zS7auWxqR+ll+b^C`vAu|u#IIDW-+sSV7WC?h z5MRQJL=Pgiieon*_Ap|fxKv^}guEexcjD6G|6K@m0Qn4rO=e4(qXL2&{dBjG=_PsLp5@OegbN9*EzuB$u z&;5d9hsEpmKWf*C^#z%ibe`A7#A`vU6%@7Xmw9uXF~qj3*h1%<+F|h&$8HyAIsc5< z6KucUF3xja*4{3nL$cm_=jYlDqF==>cJ9>PA!Zzqc|Fb%_z17KO2)2qUe#_CpHQ(9 zV(%0y4$8a{=l$AEqU8|9ZWm+De;~H@YKk2Zw>qYNn^-qWu~)PQoaOL0&iE_NW1V$W zv~cVO=bzBtQL$OZc!nPpyMx#($h(eX&%yz)9PKQ-9pb|rleF9+&bncomOI2Mj@=+y+-Cg_F{ong?wGhk+^u34xl57v zf{ZbpcZg>=Cbclx^W$3BkC7JME$&izq=lF1?+aq2h3{1{(qNB>`+~eCvt7SGh;215 z(mxQyE;o1TADmF{p&+lxyiEW5Ahy-)(LWT#sJ)L&sQ1wzkLdhZ5Fl2L;}h!r zLy$-Ho(N)8@5vxW^_~*1%9Vt9_O$q&T33Ety<9vk;&5RMy79O!$_Nd372|PJd;#ep z{EH&-IR3dUVAI4wSh~8{gHRJ=aNp|UUHtry98#_)Os{-~VGnF!gc|#RbzFF!_-u%2NWlxke6O(Ch8JUzq|TH=q4fiP=A&YxJUt&9r zsQ7j46+Hhj2HOE|6AYo`^r{h~TRW}lLG4EEtg5?#b4Ar<`Z}ikh}PqL*ucIF7Sa)I zN7WO?o!SxW8RLF!sOok>t$f=!j57brc$oYCuy#w;5$s-Q&HosuJgI%QYPWb&d#-9Z zLR#;i)V_`~Pip^C^_uZK${a^ni}m11ZDBQ)TwMJcXr{g550Kk#?$?H@zp3rluC1Pr z@aF1E%`HsZehyznnMZKO`H|{_=6><1>T40weq%rHGk%BMTg~5TiTGvU;r#gf%p=;u z`29#(9{(UhYGtZU<5k1hrs`C8Hd0;@ZK5;&d2_aYS^P^Vxi|g_(nsPin9btt@o$yds=Y)hyOn5A5G zhDfd=+7_f-hm+Es-h*iUat?dF+e3GPhhsR=l=4ZozAMPa?^NZl^=`NB)UNgJw$|x` z_Q$Qf-fv%S@7EV3);TWQUWd8vVSR048!X06i5${*B;M)VsP9b-nMd>XRNPTzp#Fb52QGDoqe8tvE6ImVE>K%i2a!TS^Iz3 z-?0C;Egajac4jzdI=h^H=dYaiI`=pqaCB%*13J?IUvWCA_ajW26izcAM0mRSFv7H3 zulpsdQIfu4XQQTvae%b|f61ryr_4|&7MdHn0#^ERVUCeLuKb&i2v`#QY2ttL^Tf12 zOp!lJh3vrXI)_^wd=W}aw{rv;o1u9w@ zg?GPL*t2nXpeI+_Tq+*O_o2qtTzRlqDCgR{`}=#kd#@C0y9<5&xvjbV!@2Sh2pFfP zeQ$SR4=5m_3iPuz*PF{9K*~11_yEW(_2+xUwnOEi+<@5BvkyHH8;1Lb^1a>Vp;fv5 z+@9{CoLGlm3>M4XJ^eYcv%7ydxBbvyPV^O3Yob^30JuxTg#r#GM9=W<-C$m>uxDtm zLf^Q3ZzF*hXEZC+jI+g!{ShD4bMA&BM&alBa?@*5UZb~-y+b&L^0~l6&B6dFDVB4B7{4J`E_d(AiLGD^25{Zxw!S{lQ5M@vhcKGO z{sX!3v{l7Q9L0fw;Q|H%1F*F_U(QW7x+;T*SUm^hJWl78xkKB)SNw=vp|^Bski~Vd zyIj7iSn3mf<3p4?I3#v#U(>R>&|Bo8Lir*|o*H6s9EVDZ=i73|V z9^89KY+Kv5Xz5uSx(nzwgpFf<4UBH%wqoy=SxH zZV2TzcbB>c%Ay_8G?bGlkgDQxmQfsCAhN`&oc!%tIh^nBTiadUE4uu=t{}6$I55cL zLP`F!B1$n*5)=@#u5h4uCFVw3`B0%3Ly1`<_&J!ID|37D1yu|pte(o-^8>l!Fl2j8 zzK}2P1(T@vJQ7_iOU3R!ntQ&ObZsVi@AB1%nk+$_#ENEA*QSDBgqY6rxse(wfzk9M z#!<`owxRCQP|zIV*fvxggieyWORVni9xUhjRv&;WY%AfIaZ@2E&57eg(NNM{qiH9G zDxUi}QPHfXVZfbLdDfcUr9)RNQmUXVwhZTnbC|RFzB1?mg*=IKg*C;J9O<%Bc`}Ak zn-KSB+d%h0rF#ZT=zV!*uD^KIqNb)ML9+dZ^xZ+`cX;EKQ0E<6j|L*iL zf$l?S0eU1?;I#F_m}GK^oh*(ud62Yq87prOEqj|uj06^LUjD>-EY0%i!tUN;Po8Mo zT+R*m6=gw0+tnj_go%%Nn4|F`W2LV^4;IG(7&m=^)}Zr-FdB_$DOV~EDw?36hKJgQa3`V%i@U$*ivwh? zDD|SO30^-`67)73RALpa?nP+;4djOQ;*F!V#qv-APBvfIF8tE%wiIzp}qMsq3RYrVt|ZXOj<||j7!|) z*n(TQ#W#n=>dJ9m`{R<^txPbigXP>nPyeCqc}&Xj zf`0O?EAxKu$rBzY%PAC$p3o(qQaed95|s^Zzn8Ef+Wxsx&#_g3Y*_Y@#;`Cc3W z<$8wq>><4~jzgwl9H3B0g~%n|A0}EyfV>n;2ARM-+?wm}KFCkyadfI86+>1}o>rOh zTvAiYN|&qf28aOJx~pl|3B>(Au|$*RTlf{t2MD8tyLDTFGe zL!|r0BcznnoFTh`>SJn^*K`l$v6NQisuV0CIcc-PfF#+2=FW8w5K{G|*s*RCtOm~7 zimirdE0wxo7-Iaz#V}NJVhtpJFE_A`HawU@*r&A(DYKqd6JAzGUsFG~7o}c+^LxWj}X{by9aj)(hp` z#S&UY6GJ&=1JeeE&3DyuWrRdc@{E@cTp+`i6J&5-(SSsxY-k_~Mxl{9Mng)L!UenX zgFf={WX4S#Rn{2MzqweJCKwIb_9FIIyuqq8MdgOKB)a?hx>UNPh6EGJUYxtUw~Nf< zL5xFte|H&Q-aL2tlCCb&f#O`>yj|YY)zu{ARz&^qo)$`EsMuTV=LnIsx-Ff&r5l+}C? zZM`(z#`kBdXyHO#UO02$GbTfywCbgHP|JTC3v~`EY<$9QFYXv5Q))X5C~gRT3G7L* zqZlUpdb}X|i>Hy@FY;?AeS%t02fh+yx8!vBoi<%dSxpU=O z-*oUSYz~^1oz>7xJ9RQIq|F7M$mp7Ujy8|vZ2=D9Ny-;7d3%YTwxPdRez##~ z0b4W&Hwdl4Y;?n9Z^t09rvhdw*|O5XqXrC92>g;mgc*a?Y<>43EcN4xS;jBIx{nLx z8}aXIX7H}-M)(}J!neLzY{%O+n-CY(+eIF4)?i;ChUr$Ew+8V7pe*(x6}8(pBd?5< zA;1BoWe}&|lGu&=rbTfTQm9S_{>UPJ%P3g_wqE=e@zjXx`x{Yy56p^j9K$Ht_m^Qg zZyo9!0G58V*N66GOVswBH>cs8mEsWEe@pb&Z8}Adv+&lUf3tU-vNsL#?qTx=aHOC6 zKgjg=DsB+RPUa|ZHk_)>LIp3Wb|dbJie+1YuMd1V2y6pri+GcP8AttHj`yrG_=ax= zWr*t;+(@L9#q^!UrER!P*^W2YSBo{c*|`>yaUp!o>%|7h$0oM>wu)_#m>ps#?$LBW zesC!Tu3KF3G8%+tbl_5B2ks$>=948Q2YLosDspHUt_-wFH1}gH(8qNfLFoWfS>l}C z2w|t<#A6tJp(moY2hXzZa>NGEi-Vw#Fz!M6Ucz+Ig-9j&qp}&)%0W6wG9(7S%?wgW zCW#98v+zr0NGkRKN}vz8(i@R0bEKS?kvAJJ!?dBq9;R6KCIgH3WNu5$z+=3PJ<9J- z-Em*5_1yX+)sG)EK6BSkg!9R(FWotH$;&tDmabclVI`&jrs`G|e(<5nDT$eycdl;D zK(q<41khqwGebs3=m0I6v9v0uD$$f!l4!9rx;8VEsK>8f6;I5zGN|mG8_H-%HtJEs zN@M`@0A~OifWa}5TV-bqEz#gqnHe!NglaQGGef{aKUJuRZ=s8-5U|gvrLd~X&6tVi zs;b1&8H7C13}kV@G7ET|swxYG5^;xqW+cv|7N~1&fQ1hFv|4u(Q40_2G>2PWNG)sH z3`aJZh?;aw5dB28nJ#68DTr`mXc8na@|hurJLiUkmY5Od5bsgp+2PQ2gr1l||5=on zm|@GfgRAAvOxHn_^UaK=&%m3*T!xEh_z~<#%m9;!x+(|MNo3)SAs>Jjv^a^mgn&pv z0Td4duR|pqfr1Y5!Am@FIn9j;bEaQEF(WRliWo|POLGA;sPPPNCNfoKJ%$Bo8-Uye zL|stOjG(WI2b7~b*1NXKirOME_BiAQ zy>*;0E>|bUp2q(yN|b~)lX#iej-VLI%nYGz{7Hf!2^e~O2Lb<{wHBW_3$h*7LJ2$U zor~gBod7k6yej;=_KC5N>F6+F#bgNCm=ro1ui}=7Y!srHZrXYk0+fo15Ygli;DsTR zXh4CGK%V156vlo)2~nDKV^1RHjs1MO9YH3>Z|qx%v42AvKm3F%PPd~(7G?e$1(kV_ zMMC0@{ktBsW$jnFk{p>Q<2JMf;{smf=s330WZv&cLShh%8uTi$LMM8_aPP3@9S(um z#O$gNP7lYPhu{-shuw&6CdOV*%tmBti1x9I(j4{rX&u}1d62Q@DmgUBwd?{f%R;ArsL3f zvL3-RHQ9gwEusun;tn33owi+QwL~;Ag~v9iQ)@?&*dPa-*-k8zV;I)K7Q+eKn1VEU z9egj`q@R#&AjAMCW<+co>c$CUlI!w0j9KnK>--$YppkZQB90TmFVG-FH5w z?VzD3(aZH2t?U`m#Jz-!;*n%v21z;wU9XxkgTkt+YTJdHpTU$TW?;mi2qEw$)*L+n zE&?m^h<2Aqo`%onQSS-3MexdraH$A&R{n=?tz(WkF8xvu^puS@WR|IhR8`8_{T#=971L%LTX$)wpr> z_Q0XHP`RegqqomAvAwD$$Wr@h+JeTZPA167EUD2%wcOg0^NCN)VL6gA5NS;$0`FVq z^ABe-i<+A8n!p*Fn7efG?v`a|Em_*oylhEJ!;(c!yBm7WTGHKcc3hB};obh85f8SqGZafDkp{TtxE5PZiV zm*YDWRN_zbfGa*;_CNbXZ-3$4NFl~1Vv_HdL1<1&r*dln9nT2yG6{wHds(N8zdNxf z>O#00JL+v}H{FHbjo3x;s|I){>X*mmO%#$A`jfxs%ZM=XTY;8SS8=JG*vpiFCy#v+ zya?E#(5{94=5np=$fccJ8ToQgP5T@9_o%r7Nb&v^b~Pp5-RzkJ(+n=t1e;L)w*>np z@Bsa#x3>J2SE2PXc2$ID5cu+-LblV+dsw*(+QvI4xl>w?GCjc4gn2iPXD62+AA(=M zxxyZm?a~`=)Kl7vmGDcu{EZ07HvuQa8@AVoom@ZuBl;7-LwiH=HsCf6S{%e)lX|cR zJ4JXnCP~ZS9%TmqEdt%RuZS|6afeRBILdmoMk)MSjMgaQ{7e M_5b(c&*Z@W0nwq%=>Px# diff --git a/Vocaluxe.sln b/Vocaluxe.sln index 0896a6f6..a493fead 100644 --- a/Vocaluxe.sln +++ b/Vocaluxe.sln @@ -1,4 +1,4 @@ - + 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}" @@ -6,6 +6,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vocaluxe", "Vocaluxe\Vocalu {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,8 @@ 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}") = "ClientServerLib", "ClientServerLib\ClientServerLib\ClientServerLib.csproj", "{EC5167E4-CCFB-4CEE-987C-CF816F1062A3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution DebugLinux|x64 = DebugLinux|x64 @@ -58,6 +61,9 @@ Global {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x64.Build.0 = DebugLinux|x64 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x86.ActiveCfg = DebugLinux|x86 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x86.Build.0 = DebugLinux|x86 + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|Mixed Platforms.ActiveCfg = DebugWin|x86 + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|Mixed Platforms.Build.0 = DebugWin|x86 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x64.ActiveCfg = DebugWin|x64 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x64.Build.0 = DebugWin|x64 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x86.ActiveCfg = DebugWin|x86 @@ -150,6 +156,16 @@ Global {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|x86.ActiveCfg = Debug|Any CPU + {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|x64.ActiveCfg = Debug|Any CPU + {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|x86.ActiveCfg = Debug|Any CPU + {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Release|x64.ActiveCfg = Release|Any CPU + {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Release|x86.ActiveCfg = Release|Any CPU + {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|x64.ActiveCfg = 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|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Vocaluxe/Base/CProfiles.cs b/Vocaluxe/Base/CProfiles.cs index d8c61652..44f996fe 100644 --- a/Vocaluxe/Base/CProfiles.cs +++ b/Vocaluxe/Base/CProfiles.cs @@ -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 . +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . #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 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; diff --git a/Vocaluxe/Base/CSettings.cs b/Vocaluxe/Base/CSettings.cs index 9fe7b69f..14790c1e 100644 --- a/Vocaluxe/Base/CSettings.cs +++ b/Vocaluxe/Base/CSettings.cs @@ -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 . +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . #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"; diff --git a/Vocaluxe/Base/Server/CCommands.cs b/Vocaluxe/Base/Server/CCommands.cs index 544f443e..5a2f545d 100644 --- a/Vocaluxe/Base/Server/CCommands.cs +++ b/Vocaluxe/Base/Server/CCommands.cs @@ -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 @@ -138,7 +138,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 +156,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(_Encoder.GetString(data)); - return true; - } - catch - { - return false; + return true; + } + catch + { + return false; } } #endregion Serializing } -} \ No newline at end of file +} diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index 557bef55..b97f225e 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -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 . +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . #endregion using System; @@ -20,7 +20,9 @@ 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 Vocaluxe.Lib.Input; @@ -40,8 +42,23 @@ namespace Vocaluxe.Base.Server public static void Init() { _Clients = new Dictionary(); - String pw = (CConfig.ServerEncryption == EOffOn.TR_CONFIG_ON) ? CConfig.ServerPassword : String.Empty; - _Server = new CServer(RequestHandler, CConfig.ServerPort, pw); + if (CConfig.ServerEncryption == EOffOn.TR_CONFIG_ON) + { + _Server = new CServer(CConfig.ServerPort); + //_Server = new CServer(RequestHandler, CConfig.ServerPort, CConfig.ServerPassword); + } + else + { + _Server = new CServer(CConfig.ServerPort); + //_Server = new CServer(RequestHandler, CConfig.ServerPort, String.Empty); + } + + CServer.SendKeyEvent = sendKeyEvent; + CServer.GetProfileData = getProfileData; + CServer.SendProfileData = sendProfileData; + CServer.GetProfileList = getProfileList; + CServer.SendPhoto = sendPhoto; + CServer.GetSiteFile = getSiteFile; _Discover = new CDiscover(CConfig.ServerPort, CCommands.BroadcastKeyword); Controller.Init(); @@ -63,147 +80,263 @@ namespace Vocaluxe.Base.Server _Clients = new Dictionary(); } - 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 (key != null && 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 ProfileData getProfileData(int profileId) + { + CProfile profile = CProfiles.GetProfile(profileId); + if (profile == null) + { + return new ProfileData(); + } + return CreateProfileData(profile); ; + } + + private static bool sendProfileData(ProfileData profile) + { + CProfile newProfile; + CProfile existingProfile = CProfiles.GetProfile(profile.ProfileId); + + if (existingProfile != null) + { + newProfile = new CProfile + { + 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) + { + //TODO:standardAvatar + } + + if (profile.PlayerName != null && profile.PlayerName != "") + { + newProfile.PlayerName = profile.PlayerName; + } + else if (newProfile.PlayerName != null && newProfile.PlayerName != "") + { + newProfile.PlayerName = "DummyName"; + } + + if (profile.Difficulty >= 0 && profile.Difficulty <= 2) + { + newProfile.Difficulty = (EGameDifficulty)profile.Difficulty; + } + + if (existingProfile != null) + { + CProfiles.EditProfile(newProfile); + } + else + { + CProfiles.AddProfile(newProfile); + } + + return true; + } + + private static ProfileData[] getProfileList() + { + List result = new List(CProfiles.NumProfiles); + + foreach (CProfile profile in CProfiles.GetProfiles()) + { + result.Add(CreateProfileData(profile)); + } + + return result.ToArray(); + } + + private static ProfileData CreateProfileData(CProfile profile) + { + ProfileData profileData = new ProfileData(); + + profileData.IsEditable = true; //TODO: set correctly + profileData.PlayerName = profile.PlayerName; + profileData.Type = (int)profile.GuestProfile; + profileData.Difficulty = (int)profile.Difficulty; + CAvatar avatar = profile.Avatar; + if (avatar != null) + { + if (File.Exists(avatar.FileName)) + { + Image avatarImage = Image.FromFile(avatar.FileName); + //TODO: Convert??? and Compress? + profileData.Avatar = new Base64Image(avatarImage, avatarImage.RawFormat); + } + } + return profileData; + } + + private static CAvatar _AddAvatar(Base64Image 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; + } + else + { + return null; } } - catch {} + catch + { + return null; + } + } - return result; + #endregion + + #region photo + + private static bool sendPhoto(PhotoData 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); + + return (filePath != null && filePath != ""); + } + + #endregion + + #region website + + 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); + } + + #endregion + + private static string _SaveImage(Base64Image imageDate, string name, string folder) + { + Image avatarImage = imageDate.getImage(); + string extension = imageDate.getImageType(); + + string filename = Path.Combine(folder, name); + int i = 0; + while (File.Exists(filename + "_" + i + "." + extension)) + { + i++; + } + filename = filename + "_" + i + "." + extension; + avatarImage.Save(filename); + return filename; } } } \ No newline at end of file diff --git a/Vocaluxe/Base/Server/VocaluxeStructs.cs b/Vocaluxe/Base/Server/VocaluxeStructs.cs index 21aa8f48..1e826831 100644 --- a/Vocaluxe/Base/Server/VocaluxeStructs.cs +++ b/Vocaluxe/Base/Server/VocaluxeStructs.cs @@ -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; } diff --git a/Vocaluxe/Vocaluxe.csproj b/Vocaluxe/Vocaluxe.csproj index 17132251..0bf1a344 100644 --- a/Vocaluxe/Vocaluxe.csproj +++ b/Vocaluxe/Vocaluxe.csproj @@ -1,4 +1,4 @@ - + DebugWin @@ -15,7 +15,8 @@ false Vocaluxe.CMainProgram Vocaluxe.ico - Client + + publish\ true Disk @@ -197,6 +198,7 @@ + @@ -310,11 +312,78 @@ + + Always + images + + + Always + images + + + Always + images + + + Always + images + + + Always + images + + + css + Always + + + css + Always + + + css + Always + + + Always + + + Always + img + + + Always + img + + + Always + img + + + Always + img + + + Always + img + + + Always + js + + + js + Always + + + js + Always + False - Microsoft .NET Framework 4 Client Profile %28x86 und x64%29 und Update für .NET Framework 4 %28KB2468871%29 + Microsoft .NET Framework 4 Client Profile %28x86 und x64%29 und Update für .NET Framework 4 %28KB2468871%29 true @@ -324,11 +393,18 @@ + + {ec5167e4-ccfb-4cee-987c-cf816f1062a3} + ClientServerLib + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC} VocaluxeLib + + + + + + + + + +
+
+

All profiles

+
+ + +
+
    +
    + +
    + + + +
    +
    +

    Profile

    +
    + + +
    + Avatar + + + + + + + + Save and upload +
    + +
    + + +
    +
    +

    Keyboard

    +
    + + +
    +
    +
    +
    + up +
    +
    +
    + left +
    +
    +
    +
    + right +
    +
    +
    + down +
    +
    +
    +
    +
    + escape +
    +
    + tab +
    +
    + return +
    +
    +
    + + +
    +
    + +
    + + +
    + + + + diff --git a/Vocaluxe/Website/js/jquery-1.9.1.min.js b/Vocaluxe/Website/js/jquery-1.9.1.min.js new file mode 100644 index 00000000..006e9531 --- /dev/null +++ b/Vocaluxe/Website/js/jquery-1.9.1.min.js @@ -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(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
    a",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="
    t
    ",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
    ",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj; +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+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="
    ",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&>(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:b.support.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l) +}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}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b(" + + diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index a43136bf..e2418430 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -11,6 +11,7 @@ $(document).ready(function () { initMainPageHandler(); initLoginPageHandler(); initHeartbeat(); + initVideoPopup(); }); function replaceTransitionHandler() { @@ -234,6 +235,20 @@ function initPageLoadHandler() { } $('#displaySongIsDuet').text(result.IsDuet ? "Yes" : "No"); + + if (result.Title != null || result.Artist != null) { + $('#displaySongLinks').show(); + + $('#displaySongLinkYoutube').unbind('click').click(function () { + showYoutube(result.Artist, result.Title); + }); + + $('#displaySongLinkSpotify').unbind('click').click(function () { + showSpotify(result.Artist, result.Title); + }); + } else { + $('#displaySongLinks').hide(); + } }); // Save promise on page so the transition handler can find it. @@ -586,11 +601,16 @@ function request(data, message) { textVisible: true }); } - + if (!data["headers"]) { data["headers"] = {}; } - data["headers"]["session"] = sessionId; + + if (message == "external") { + message = "Loading (external)..."; + } else { + data["headers"]["session"] = sessionId; + } return $.ajax(data).always(function (result) { if (message != "noOverlay") { @@ -616,7 +636,7 @@ function showError(message) { if (!message) { message = "Error..."; } - + $('div[data-role="content"]').wrap('
    '); $.mobile.loading('show', { text: message, @@ -624,9 +644,99 @@ function showError(message) { }); $('.ui-loader').find('span').removeClass('ui-icon-loading').addClass('ui-custom-errorIcon'); - setTimeout(function() { + setTimeout(function () { $.mobile.loading('hide'); $('div[data-role="content"]').unwrap(); $('.ui-loader').find('span').removeClass('ui-custom-errorIcon').addClass('ui-icon-loading'); }, 1000); +} + +var popupVideoHeight = 390; +var popupVideoWidth = 640; +function initVideoPopup() { + function scale(width, height, padding, border) { + var scrWidth = $(window).width() - 30, + scrHeight = $(window).height() - 30, + ifrPadding = 2 * padding, + ifrBorder = 2 * border, + ifrWidth = width + ifrPadding + ifrBorder, + ifrHeight = height + ifrPadding + ifrBorder, + h, w; + + if (ifrWidth < scrWidth && ifrHeight < scrHeight) { + w = ifrWidth; + h = ifrHeight; + } else if ((ifrWidth / scrWidth) > (ifrHeight / scrHeight)) { + w = scrWidth; + h = (scrWidth / ifrWidth) * ifrHeight; + } else { + h = scrHeight; + w = (scrHeight / ifrHeight) * ifrWidth; + } + + return { + 'width': w - (ifrPadding + ifrBorder), + 'height': h - (ifrPadding + ifrBorder) + }; + }; + $("#popupVideo").find("a").click(function () { + $("#popupVideo").popup("close"); + $("#popupVideo").popup("close"); //Sometimes twice?? + }); + + $("#popupVideo iframe") + .attr("width", 0) + .attr("height", 0); + + $("#popupVideo").on({ + popupbeforeposition: function () { + var size = scale(popupVideoWidth, popupVideoHeight, 15, 1), + w = size.width, + h = size.height; + + $("#popupVideo iframe") + .attr("width", w) + .attr("height", h); + }, + popupafterclose: function () { + $("#popupVideo iframe") + .attr("width", 0) + .attr("height", 0) + .attr("src", ""); + } + }); +}; + +function showYoutube(artist, title) { + request({ + url: "http://gdata.youtube.com/feeds/api/videos/-/Music?max-results=1&alt=json&format=5&q=" + artist + " " + title, + dataType: "json", + }, "external") + .done(function (result) { + if (result && result.feed && result.feed.entry && result.feed.entry.length > 0) { + var vidId = result.feed.entry[0].id.$t.replace("http://gdata.youtube.com/feeds/api/videos/", ""); + popupVideoHeight = 390; + popupVideoWidth = 640; + + $("#popupVideo iframe").attr("src", "http://www.youtube.com/embed/" + vidId + "?&autoplay=1&rel=0&showinfo=0&disablekb=1&autohide=1"); + $("#popupVideo").popup("open"); + } + }); +} + +function showSpotify(artist, title) { + request({ + url: "http://ws.spotify.com/search/1/track.json?q=" + title + "+artist:" + artist, + dataType: "json", + }, "external") + .done(function (result) { + if (result && result.tracks && result.tracks.length > 0) { + var spotId = result.tracks[0].href; + popupVideoHeight = 80; + popupVideoWidth = 300; + + $("#popupVideo iframe").attr("src", "https://embed.spotify.com/?uri=" + spotId); + $("#popupVideo").popup("open"); + } + }); } \ No newline at end of file From 3344f05b58c74be5c6c7d77e521aca463da0a774 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sat, 26 Oct 2013 11:00:08 +0200 Subject: [PATCH 29/81] Webserver: renaming --- ClientServerLib/ClientServerLib/CServer.cs | 165 ++++++------- .../ClientServerLib/CWebservice.cs | 233 ++++++++++-------- .../ClientServerLib/DataStructs.cs | 38 ++- ClientServerLib/ClientServerLib/Session.cs | 27 +- .../ClientServerLib/SessionControl.cs | 45 ++-- ClientServerLib/ClientServerLib/UserRights.cs | 5 +- .../ClientServerLib/UserRoleControl.cs | 39 ++- ClientServerLib/ClientServerLib/UserRoles.cs | 5 +- Vocaluxe/Base/Server/CVocaluxeServer.cs | 169 ++++++------- 9 files changed, 359 insertions(+), 367 deletions(-) diff --git a/ClientServerLib/ClientServerLib/CServer.cs b/ClientServerLib/ClientServerLib/CServer.cs index 3ae61191..59d9e173 100644 --- a/ClientServerLib/ClientServerLib/CServer.cs +++ b/ClientServerLib/ClientServerLib/CServer.cs @@ -1,11 +1,6 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.ServiceModel; -using System.ServiceModel.Description; using System.ServiceModel.Web; -using System.Security.Cryptography.X509Certificates; using System.Diagnostics; using System.Net; @@ -13,91 +8,91 @@ namespace ServerLib { public class CServer { - private ServiceHost host; - private Uri baseAddress; - private bool encrypted = false; + private ServiceHost _Host; + private Uri _BaseAddress; + private bool _Encrypted = false; - private static SendKeyEventDelegate sendKeyEvent; + private static SendKeyEventDelegate _SendKeyEvent; public static SendKeyEventDelegate SendKeyEvent { - internal get { return CServer.sendKeyEvent; } - set { CServer.sendKeyEvent = value; } + internal get { return CServer._SendKeyEvent; } + set { CServer._SendKeyEvent = value; } } #region profile - private static GetProfileDataDelegate getProfileData; + private static GetProfileDataDelegate _GetProfileData; public static GetProfileDataDelegate GetProfileData { - internal get { return CServer.getProfileData; } - set { CServer.getProfileData = value; } + internal get { return CServer._GetProfileData; } + set { CServer._GetProfileData = value; } } - private static SendProfileDataDelegate sendProfileData; + private static SendProfileDataDelegate _SendProfileData; public static SendProfileDataDelegate SendProfileData { - internal get { return CServer.sendProfileData; } - set { CServer.sendProfileData = value; } + internal get { return CServer._SendProfileData; } + set { CServer._SendProfileData = value; } } - private static GetProfileListDelegate getProfileList; + private static GetProfileListDelegate _GetProfileList; public static GetProfileListDelegate GetProfileList { - internal get { return CServer.getProfileList; } - set { CServer.getProfileList = value; } + internal get { return CServer._GetProfileList; } + set { CServer._GetProfileList = value; } } #endregion #region photo - private static SendPhotoDelegate sendPhoto; + private static SendPhotoDelegate _SendPhoto; public static SendPhotoDelegate SendPhoto { - get { return CServer.sendPhoto; } - set { CServer.sendPhoto = value; } + get { return CServer._SendPhoto; } + set { CServer._SendPhoto = value; } } #endregion #region website - private static GetSiteFileDelegate getSiteFile; + private static GetSiteFileDelegate _GetSiteFile; public static GetSiteFileDelegate GetSiteFile { - internal get { return CServer.getSiteFile; } - set { CServer.getSiteFile = value; } + internal get { return CServer._GetSiteFile; } + set { CServer._GetSiteFile = value; } } - private static GetDelayedImageDelegate getDelayedImage; + private static GetDelayedImageDelegate _GetDelayedImage; public static GetDelayedImageDelegate GetDelayedImage { - internal get { return CServer.getDelayedImage; } - set { CServer.getDelayedImage = value; } + internal get { return CServer._GetDelayedImage; } + set { CServer._GetDelayedImage = value; } } #endregion #region songs - private static GetSongDelegate getSong; + private static GetSongDelegate _GetSong; public static GetSongDelegate GetSong { - internal get { return CServer.getSong; } - set { CServer.getSong = value; } + internal get { return CServer._GetSong; } + set { CServer._GetSong = value; } } - private static GetAllSongsDelegate getAllSongs; + private static GetAllSongsDelegate _GetAllSongs; public static GetAllSongsDelegate GetAllSongs { - get { return CServer.getAllSongs; } - set { CServer.getAllSongs = value; } + get { return CServer._GetAllSongs; } + set { CServer._GetAllSongs = value; } } - private static GetCurrentSongIdDelegate getCurrentSongId; + private static GetCurrentSongIdDelegate _GetCurrentSongId; public static GetCurrentSongIdDelegate GetCurrentSongId { - get { return CServer.getCurrentSongId; } - set { CServer.getCurrentSongId = value; } + get { return CServer._GetCurrentSongId; } + set { CServer._GetCurrentSongId = value; } } @@ -105,77 +100,77 @@ namespace ServerLib #region user management - private static SetPasswordDelegate setPassword; + private static SetPasswordDelegate _SetPassword; public static SetPasswordDelegate SetPassword { - internal get { return CServer.setPassword; } - set { CServer.setPassword = value; } + internal get { return CServer._SetPassword; } + set { CServer._SetPassword = value; } } - private static ValidatePasswordDelegate validatePassword; + private static ValidatePasswordDelegate _ValidatePassword; public static ValidatePasswordDelegate ValidatePassword { - internal get { return CServer.validatePassword; } - set { CServer.validatePassword = value; } + internal get { return CServer._ValidatePassword; } + set { CServer._ValidatePassword = value; } } - private static GetUserRoleDelegate getUserRole; + private static GetUserRoleDelegate _GetUserRole; public static GetUserRoleDelegate GetUserRole { - internal get { return CServer.getUserRole; } - set { CServer.getUserRole = value; } + internal get { return CServer._GetUserRole; } + set { CServer._GetUserRole = value; } } - private static SetUserRoleDelegate setUserRole; + private static SetUserRoleDelegate _SetUserRole; public static SetUserRoleDelegate SetUserRole { - internal get { return CServer.setUserRole; } - set { CServer.setUserRole = value; } + internal get { return CServer._SetUserRole; } + set { CServer._SetUserRole = value; } } - private static GetUserIdFromUsernameDelegate getUserIdFromUsername; + private static GetUserIdFromUsernameDelegate _GetUserIdFromUsername; public static GetUserIdFromUsernameDelegate GetUserIdFromUsername { - internal get { return CServer.getUserIdFromUsername; } - set { CServer.getUserIdFromUsername = value; } + internal get { return CServer._GetUserIdFromUsername; } + set { CServer._GetUserIdFromUsername = value; } } #endregion public CServer(int port, bool encrypted) { - init(port, encrypted); + _Init(port, encrypted); } #region server control - private void init(int port, bool encrypted) + private void _Init(int port, bool encrypted) { string hostname = Dns.GetHostName(); if (encrypted) { - baseAddress = new Uri("https://" + hostname + ":" + port + "/"); + _BaseAddress = new Uri("https://" + hostname + ":" + port + "/"); } else { - baseAddress = new Uri("http://" + hostname + ":" + port + "/"); + _BaseAddress = new Uri("http://" + hostname + ":" + port + "/"); } - this.encrypted = encrypted; - host = new WebServiceHost(typeof(CWebservice), baseAddress); + this._Encrypted = encrypted; + _Host = new WebServiceHost(typeof(CWebservice), _BaseAddress); - WebHttpBinding wb = new WebHttpBinding(); - wb.MaxReceivedMessageSize = 10485760; - wb.MaxBufferSize = 10485760; - wb.MaxBufferPoolSize = 10485760; - wb.ReaderQuotas.MaxStringContentLength = 10485760; - wb.ReaderQuotas.MaxArrayLength = 10485760; - wb.ReaderQuotas.MaxBytesPerRead = 10485760; + 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, ""); + _Host.AddServiceEndpoint(typeof(ICWebservice), wb, ""); } public void Start() @@ -187,27 +182,27 @@ namespace ServerLib smb.HttpGetEnabled = true; host.Description.Behaviors.Add(smb);*/ - host.Open(); + _Host.Open(); } catch (CommunicationException e) { if (e is AddressAccessDeniedException || e is AddressAlreadyInUseException) { - registerUrlAndCert(baseAddress.Port); + _RegisterUrlAndCert(_BaseAddress.Port); try { - host.Abort(); - init(baseAddress.Port, encrypted); - host.Open(); + _Host.Abort(); + _Init(_BaseAddress.Port, _Encrypted); + _Host.Open(); } catch (CommunicationException e2) { - host.Abort(); + _Host.Abort(); } } else { - host.Abort(); + _Host.Abort(); } } } @@ -216,25 +211,27 @@ namespace ServerLib { try { - host.Close(); + _Host.Close(); } catch (CommunicationException e) { - host.Abort(); + _Host.Abort(); } } - private void registerUrlAndCert(int port) + private void _RegisterUrlAndCert(int port) { #if WIN - ProcessStartInfo info = new ProcessStartInfo(); - info.FileName = "WebserverInitalConfig.exe"; - info.Arguments = port.ToString() + " " + encrypted.ToString(); - info.UseShellExecute = true; - info.CreateNoWindow = true; - info.WindowStyle = ProcessWindowStyle.Hidden; - info.Verb = "runas"; + ProcessStartInfo info = new ProcessStartInfo + { + FileName = "WebserverInitalConfig.exe", + Arguments = port.ToString() + " " + _Encrypted.ToString(), + UseShellExecute = true, + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + Verb = "runas" + }; Process p = Process.Start(info); if (p != null) { diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs index 34f493da..6b54e961 100644 --- a/ClientServerLib/ClientServerLib/CWebservice.cs +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -1,10 +1,6 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.ServiceModel; -using System.Text; using System.ServiceModel.Web; -using System.Web.Services; using System.IO; using System.ServiceModel.Channels; @@ -17,7 +13,7 @@ namespace ServerLib [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/sendKeyEvent?key={key}")] - void sendKeyEvent(string key); + void SendKeyEvent(string key); #region profile @@ -25,25 +21,25 @@ namespace ServerLib [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/getOwnProfileId")] - int getOwnProfileId(); + int GetOwnProfileId(); [OperationContract] [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/sendProfile")] - void sendProfile(ProfileData profile); + void SendProfile(SProfileData profile); [OperationContract] [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/getProfile?profileId={profileId}")] - ProfileData getProfile(int profileId); + SProfileData GetProfile(int profileId); [OperationContract] [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/getProfileList")] - ProfileData[] getProfileList(); + SProfileData[] GetProfileList(); #endregion @@ -54,7 +50,7 @@ namespace ServerLib RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "/sendPhoto")] - void sendPhoto(PhotoData photo); + void SendPhoto(SPhotoData photo); #endregion @@ -64,7 +60,7 @@ namespace ServerLib [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/login?username={username}&password={password}")] - Guid login(string username, string password); + Guid Login(string username, string password); [OperationContract] [WebInvoke(Method = "GET", @@ -100,7 +96,7 @@ namespace ServerLib [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/delayedImage?id={id}")] - Base64Image GetDelayedImage(String id); + CBase64Image GetDelayedImage(String id); #endregion @@ -110,19 +106,19 @@ namespace ServerLib [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/getSong?songId={songId}")] - SongInfo getSong(int songId); + SOngInfo GetSong(int songId); [OperationContract] [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/getCurrentSongId")] - int getCurrentSongId(); + int GetCurrentSongId(); [OperationContract] [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/getAllSongs")] - SongInfo[] getAllSongs(); + SOngInfo[] GetAllSongs(); #endregion @@ -132,29 +128,25 @@ namespace ServerLib [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/getUserRole?profileId={profileId}")] - int getUserRole(int profileId); + int GetUserRole(int profileId); [OperationContract] [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/setUserRole?profileId={profileId}&userRole={userRole}")] - void setUserRole(int profileId, int userRole); + void SetUserRole(int profileId, int userRole); #endregion } class CWebservice : ICWebservice { - public CWebservice() - { - } - - private static Guid getSession() + private static Guid _GetSession() { Guid sessionKey = Guid.Empty; string sessionHeader = ((HttpRequestMessageProperty)OperationContext.Current.IncomingMessageProperties["httpRequest"]).Headers["session"]; - if (sessionHeader == null || sessionHeader == "") + if (string.IsNullOrEmpty(sessionHeader)) { return sessionKey; } @@ -168,25 +160,33 @@ namespace ServerLib return sessionKey; } - public void sendKeyEvent(string key) + public void SendKeyEvent(string key) { - Guid sessionKey = getSession(); + Guid sessionKey = _GetSession(); - if (sessionKey == Guid.Empty ) + if (sessionKey == Guid.Empty) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; - + if (WebOperationContext.Current != null) + { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; + WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; + } } - else if (!SessionControl.requestRight(sessionKey, UserRights.UseKeyboard)) + else if (!CSessionControl.RequestRight(sessionKey, EUserRights.UseKeyboard)) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; + if (WebOperationContext.Current != null) + { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; + WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; + } } else if (CServer.SendKeyEvent == null) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not found"; + if (WebOperationContext.Current != null) + { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound; + WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not found"; + } } else { @@ -196,51 +196,66 @@ namespace ServerLib #region profile - public int getOwnProfileId() + public int GetOwnProfileId() { - Guid sessionKey = getSession(); + Guid sessionKey = _GetSession(); if (sessionKey == Guid.Empty) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; + if (WebOperationContext.Current != null) + { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; + WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; + } return -1; } - int profileId = SessionControl.getUserIdFromSession(sessionKey); + int profileId = CSessionControl.GetUserIdFromSession(sessionKey); if (profileId < 0) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; + 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(ProfileData profile) + public void SendProfile(SProfileData profile) { - Guid sessionKey = getSession(); + Guid sessionKey = _GetSession(); if (profile.ProfileId != -1) //-1 is the id for a new profile { if (sessionKey == Guid.Empty) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; + if (WebOperationContext.Current != null) + { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; + WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; + } return; } - if (!SessionControl.requestRight(sessionKey, UserRights.EditAllProfiles) && - SessionControl.getUserIdFromSession(sessionKey) != profile.ProfileId) + if (!CSessionControl.RequestRight(sessionKey, EUserRights.EditAllProfiles) && + CSessionControl.GetUserIdFromSession(sessionKey) != profile.ProfileId) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; + if (WebOperationContext.Current != null) + { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; + WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; + } return; } } if (CServer.SendProfileData == null) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not found"; + if (WebOperationContext.Current != null) + { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound; + WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not found"; + } return; } @@ -258,41 +273,47 @@ namespace ServerLib } } - public ProfileData getProfile(int profileId) + public SProfileData GetProfile(int profileId) { - Guid sessionKey = getSession(); + Guid sessionKey = _GetSession(); if (sessionKey == Guid.Empty) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; - return new ProfileData(); + if (WebOperationContext.Current != null) + { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; + WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; + } + return new SProfileData(); } - if (!SessionControl.requestRight(sessionKey, UserRights.ViewOtherProfiles) && - SessionControl.getUserIdFromSession(sessionKey) != profileId) + if (!CSessionControl.RequestRight(sessionKey, EUserRights.ViewOtherProfiles) && + CSessionControl.GetUserIdFromSession(sessionKey) != profileId) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; - return new ProfileData(); + if (WebOperationContext.Current != null) + { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; + WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; + } + return new SProfileData(); } if (CServer.GetProfileData == null) { - return new ProfileData(); + return new SProfileData(); } - bool isReadonly = (!SessionControl.requestRight(sessionKey, UserRights.EditAllProfiles) && - SessionControl.getUserIdFromSession(sessionKey) != profileId); + bool isReadonly = (!CSessionControl.RequestRight(sessionKey, EUserRights.EditAllProfiles) && + CSessionControl.GetUserIdFromSession(sessionKey) != profileId); return CServer.GetProfileData(profileId, isReadonly); } - public ProfileData[] getProfileList() + public SProfileData[] GetProfileList() { if (CServer.GetProfileList == null) { - return new ProfileData[] { }; + return new SProfileData[] { }; } return CServer.GetProfileList(); } @@ -301,20 +322,26 @@ namespace ServerLib #region photo - public void sendPhoto(PhotoData photo) + public void SendPhoto(SPhotoData photo) { - Guid sessionKey = getSession(); + Guid sessionKey = _GetSession(); if (sessionKey == Guid.Empty) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; + if (WebOperationContext.Current != null) + { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; + WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; + } return; } - if (!SessionControl.requestRight(sessionKey, UserRights.UploadPhotos)) + if (!CSessionControl.RequestRight(sessionKey, EUserRights.UploadPhotos)) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; + if (WebOperationContext.Current != null) + { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; + WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; + } return; } @@ -325,13 +352,16 @@ namespace ServerLib #region website - public Guid login(string username, string password) + public Guid Login(string username, string password) { - Guid sessionId = SessionControl.openSession(username, password); + Guid sessionId = CSessionControl.OpenSession(username, password); if (sessionId == Guid.Empty) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "Wrong username or password"; + if (WebOperationContext.Current != null) + { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; + WebOperationContext.Current.OutgoingResponse.StatusDescription = "Wrong username or password"; + } } return sessionId; } @@ -359,11 +389,12 @@ namespace ServerLib { return new MemoryStream(data); } - else + + if (WebOperationContext.Current != null) { WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound; - return null; } + return null; } public Stream GetCssFile(string filename) @@ -379,13 +410,11 @@ namespace ServerLib { return new MemoryStream(data); } - else + if (WebOperationContext.Current != null) { WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound; - return null; } - - + return null; } public Stream GetCssImageFile(string filename) @@ -401,11 +430,11 @@ namespace ServerLib { return new MemoryStream(data); } - else + if (WebOperationContext.Current != null) { WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound; - return null; } + return null; } public Stream GetImgFile(string filename) @@ -421,14 +450,14 @@ namespace ServerLib { return new MemoryStream(data); } - else + if (WebOperationContext.Current != null) { WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.NotFound; - return null; } + return null; } - public Base64Image GetDelayedImage(string id) + public CBase64Image GetDelayedImage(string id) { return CServer.GetDelayedImage(id); } @@ -437,43 +466,47 @@ namespace ServerLib #region songs - public SongInfo getSong(int songId) + public SOngInfo GetSong(int songId) { return CServer.GetSong(songId); } - public int getCurrentSongId() + public int GetCurrentSongId() { return CServer.GetCurrentSongId(); } - public SongInfo[] getAllSongs() + public SOngInfo[] GetAllSongs() { return CServer.GetAllSongs(); } #endregion - #region user management + #region user management - public int getUserRole(int profileId) + public int GetUserRole(int profileId) { return CServer.GetUserRole(profileId); } - public void setUserRole(int profileId, int userRole) + public void SetUserRole(int profileId, int userRole) { - Guid sessionKey = getSession(); + Guid sessionKey = _GetSession(); if (sessionKey == Guid.Empty) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; + if (WebOperationContext.Current != null) { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; + WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; + } return; } - if (!SessionControl.requestRight(sessionKey, UserRights.EditAllProfiles)) + if (!CSessionControl.RequestRight(sessionKey, EUserRights.EditAllProfiles)) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; + if (WebOperationContext.Current != null) { + WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; + WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; + } return; } CServer.SetUserRole(profileId, userRole); diff --git a/ClientServerLib/ClientServerLib/DataStructs.cs b/ClientServerLib/ClientServerLib/DataStructs.cs index ccd9a1a4..8eba693d 100644 --- a/ClientServerLib/ClientServerLib/DataStructs.cs +++ b/ClientServerLib/ClientServerLib/DataStructs.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Runtime.Serialization; using System.Drawing; using System.IO; @@ -15,15 +13,15 @@ namespace ServerLib #region profile - public delegate ProfileData GetProfileDataDelegate(int profileId, bool isReadonly); - public delegate bool SendProfileDataDelegate(ProfileData profile); - public delegate ProfileData[] GetProfileListDelegate(); + public delegate SProfileData GetProfileDataDelegate(int profileId, bool isReadonly); + public delegate bool SendProfileDataDelegate(SProfileData profile); + public delegate SProfileData[] GetProfileListDelegate(); [DataContract] - public struct ProfileData + public struct SProfileData { [DataMember] - public Base64Image Avatar; + public CBase64Image Avatar; [DataMember] public string PlayerName; [DataMember] @@ -42,13 +40,13 @@ namespace ServerLib #region photo - public delegate bool SendPhotoDelegate(PhotoData photo); + public delegate bool SendPhotoDelegate(SPhotoData photo); [DataContract] - public struct PhotoData + public struct SPhotoData { [DataMember] - public Base64Image Photo; + public CBase64Image Photo; //Add infomation about the user who took this image?? } @@ -58,12 +56,12 @@ namespace ServerLib public delegate byte[] GetSiteFileDelegate(string filename); - public delegate Base64Image GetDelayedImageDelegate(string hashedFilename); + public delegate CBase64Image GetDelayedImageDelegate(string hashedFilename); #endregion [DataContract] - public class Base64Image + public class CBase64Image { [DataMember] private string base64Data = ""; @@ -71,7 +69,7 @@ namespace ServerLib [DataMember] private string imageId = ""; - public Base64Image(Image img, ImageFormat format) + public CBase64Image(Image img, ImageFormat format) { MemoryStream ms = new MemoryStream(); img.Save(ms, format); @@ -79,12 +77,12 @@ namespace ServerLib base64Data = "data:image/" + formatString + ";base64," + Convert.ToBase64String(ms.ToArray()); } - public Base64Image(string imageId) + public CBase64Image(string imageId) { this.imageId = imageId; } - public Image getImage() + public Image GetImage() { string onlyBase64Data = base64Data.Substring(base64Data.IndexOf(";base64,") + (";base64,").Length); byte[] imageData = Convert.FromBase64String(onlyBase64Data); @@ -94,7 +92,7 @@ namespace ServerLib return image; } - public string getImageType() + public string GetImageType() { Match match = Regex.Match(base64Data, "(?<=data:image/)[a-zA-Z]+(?=;base64)"); return match.Success ? match.Groups[0].Value : ""; @@ -105,21 +103,21 @@ namespace ServerLib #region songs - public delegate SongInfo GetSongDelegate(int songId); + public delegate SOngInfo GetSongDelegate(int songId); - public delegate SongInfo[] GetAllSongsDelegate(); + public delegate SOngInfo[] GetAllSongsDelegate(); public delegate int GetCurrentSongIdDelegate(); [DataContract] - public struct SongInfo + public struct SOngInfo { [DataMember] public string Title; [DataMember] public string Artist; [DataMember] - public Base64Image Cover; + public CBase64Image Cover; [DataMember] public string Genre { get; set; } [DataMember] diff --git a/ClientServerLib/ClientServerLib/Session.cs b/ClientServerLib/ClientServerLib/Session.cs index 3eee930f..b482fe53 100644 --- a/ClientServerLib/ClientServerLib/Session.cs +++ b/ClientServerLib/ClientServerLib/Session.cs @@ -1,35 +1,32 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace ServerLib { - internal class Session + internal class CSession { - Guid id; + readonly Guid _ID; public Guid Id { - get { return id; } + get { return _ID; } } - int profileId; + readonly int _ProfileId; public int ProfileId { - get { return profileId; } + get { return _ProfileId; } } - UserRoles roles; - internal UserRoles Roles + readonly EUserRoles _Roles; + internal EUserRoles Roles { - get { return roles; } + get { return _Roles; } } - public Session(Guid id, int profileId, UserRoles roles) + public CSession(Guid id, int profileId, EUserRoles roles) { - this.id = id; - this.profileId = profileId; - this.roles = roles; + this._ID = id; + this._ProfileId = profileId; + this._Roles = roles; } } } diff --git a/ClientServerLib/ClientServerLib/SessionControl.cs b/ClientServerLib/ClientServerLib/SessionControl.cs index c042803f..cf92484d 100644 --- a/ClientServerLib/ClientServerLib/SessionControl.cs +++ b/ClientServerLib/ClientServerLib/SessionControl.cs @@ -1,69 +1,68 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; namespace ServerLib { - internal static class SessionControl + internal static class CSessionControl { - private static Dictionary activeSessions = new Dictionary(); + private static readonly Dictionary _ActiveSessions = new Dictionary(); - public static Guid openSession(string userName, string password) + public static Guid OpenSession(string userName, string password) { - if (!validateUserAndPassword(userName, password)) + if (!_ValidateUserAndPassword(userName, password)) { return Guid.Empty; } Guid newId = Guid.NewGuid(); - int id = getProfileIdFormUsername(userName); - UserRoles roles = getUserRoles(id); - Session session = new Session(newId, id, roles); - invalidateSessions(id); - activeSessions.Add(newId, session); + 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) + private static bool _ValidateUserAndPassword(string userName, string password) { - return CServer.ValidatePassword(getProfileIdFormUsername(userName), password); + return CServer.ValidatePassword(_GetProfileIdFormUsername(userName), password); } - private static int getProfileIdFormUsername(string username) + private static int _GetProfileIdFormUsername(string username) { return CServer.GetUserIdFromUsername(username); } - private static UserRoles getUserRoles(int profileId) + private static EUserRoles _GetUserRoles(int profileId) { - return (UserRoles)CServer.GetUserRole(profileId); + return (EUserRoles)CServer.GetUserRole(profileId); } - internal static void invalidateSessions(int profileId) + internal static void InvalidateSessions(int profileId) { - foreach (var s in (from kv in activeSessions + foreach (var s in (from kv in _ActiveSessions where kv.Value.ProfileId == profileId select kv).ToList()) { - activeSessions.Remove(s.Key); + _ActiveSessions.Remove(s.Key); } } - internal static bool requestRight(Guid sessionId, UserRights requestedRight) + internal static bool RequestRight(Guid sessionId, EUserRights requestedRight) { - return ((UserRoleControl.getUserRightsFromUserRole(activeSessions[sessionId].Roles) & requestedRight) != 0); + return ((CUserRoleControl.GetUserRightsFromUserRole(_ActiveSessions[sessionId].Roles) & requestedRight) != 0); } - internal static int getUserIdFromSession(Guid sessionId) + internal static int GetUserIdFromSession(Guid sessionId) { - if (!activeSessions.ContainsKey(sessionId)) + if (!_ActiveSessions.ContainsKey(sessionId)) { return -1; } - return activeSessions[sessionId].ProfileId; + return _ActiveSessions[sessionId].ProfileId; } } } diff --git a/ClientServerLib/ClientServerLib/UserRights.cs b/ClientServerLib/ClientServerLib/UserRights.cs index 3a7091ea..3d02b056 100644 --- a/ClientServerLib/ClientServerLib/UserRights.cs +++ b/ClientServerLib/ClientServerLib/UserRights.cs @@ -1,12 +1,9 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace ServerLib { [Flags] - internal enum UserRights + internal enum EUserRights { None = 0x00, EditAllProfiles = 0x01, diff --git a/ClientServerLib/ClientServerLib/UserRoleControl.cs b/ClientServerLib/ClientServerLib/UserRoleControl.cs index 50845589..3c5eaa0e 100644 --- a/ClientServerLib/ClientServerLib/UserRoleControl.cs +++ b/ClientServerLib/ClientServerLib/UserRoleControl.cs @@ -1,35 +1,28 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using System.Text; namespace ServerLib { - internal static class UserRoleControl + internal static class CUserRoleControl { - private static Dictionary roleRightsMapping = new Dictionary { - {UserRoles.Administrator, - (UserRights.EditAllProfiles| - UserRights.UploadPhotos| - UserRights.ViewOtherProfiles)| - UserRights.UseKeyboard}, - {UserRoles.AuthenticatedUser, - (UserRights.UploadPhotos| - UserRights.ViewOtherProfiles| - UserRights.UseKeyboard)} + private static readonly Dictionary _RoleRightsMapping = new Dictionary { + {EUserRoles.Administrator, + (EUserRights.EditAllProfiles| + EUserRights.UploadPhotos| + EUserRights.ViewOtherProfiles)| + EUserRights.UseKeyboard}, + {EUserRoles.AuthenticatedUser, + (EUserRights.UploadPhotos| + EUserRights.ViewOtherProfiles| + EUserRights.UseKeyboard)} }; - internal static UserRights getUserRightsFromUserRole(UserRoles userRole) + internal static EUserRights GetUserRightsFromUserRole(EUserRoles userRole) { - UserRights resultRights = UserRights.None; - - foreach (UserRights r in roleRightsMapping.Where(role => userRole.HasFlag(role.Key)).Select(role => role.Value)) - { - resultRights |= r; - } - - return resultRights; + return _RoleRightsMapping.Where(role => userRole.HasFlag(role.Key)) + .Select(role => role.Value) + .Aggregate(EUserRights.None, (current, r) => current | r); } } } diff --git a/ClientServerLib/ClientServerLib/UserRoles.cs b/ClientServerLib/ClientServerLib/UserRoles.cs index 0cc8d48c..0294a029 100644 --- a/ClientServerLib/ClientServerLib/UserRoles.cs +++ b/ClientServerLib/ClientServerLib/UserRoles.cs @@ -1,12 +1,9 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace ServerLib { [Flags] - internal enum UserRoles + internal enum EUserRoles { AuthenticatedUser = 0x00, Administrator = 0x01 diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index dcb1c38f..45340056 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -18,8 +18,6 @@ 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; @@ -48,21 +46,21 @@ namespace Vocaluxe.Base.Server _Server = new CServer(CConfig.ServerPort, CConfig.ServerEncryption == EOffOn.TR_CONFIG_ON); //TODO: remove CConfig.ServerPassword - 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.SetPassword = setPassword; - CServer.ValidatePassword = validatePassword; - CServer.GetUserRole = getUserRole; - CServer.SetUserRole = setUserRole; - CServer.GetUserIdFromUsername = getUserIdFromUsername; - CServer.GetDelayedImage = getDelayedImage; + 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.SetPassword = _SetPassword; + CServer.ValidatePassword = _ValidatePassword; + CServer.GetUserRole = _GetUserRole; + CServer.SetUserRole = _SetUserRole; + CServer.GetUserIdFromUsername = _GetUserIdFromUsername; + CServer.GetDelayedImage = _GetDelayedImage; _Discover = new CDiscover(CConfig.ServerPort, CCommands.BroadcastKeyword); Controller.Init(); @@ -84,7 +82,7 @@ namespace Vocaluxe.Base.Server _Clients = new Dictionary(); } - private static bool sendKeyEvent(string key) + private static bool _SendKeyEvent(string key) { bool result = false; if (key != null && key != "") @@ -155,17 +153,17 @@ namespace Vocaluxe.Base.Server #region profile - private static ProfileData getProfileData(int profileId, bool isReadonly) + private static SProfileData _GetProfileData(int profileId, bool isReadonly) { CProfile profile = CProfiles.GetProfile(profileId); if (profile == null) { - return new ProfileData(); + return new SProfileData(); } - return CreateProfileData(profile, isReadonly); ; + return _CreateProfileData(profile, isReadonly); } - private static bool sendProfileData(ProfileData profile) + private static bool _SendProfileData(SProfileData profile) { CProfile newProfile; CProfile existingProfile = CProfiles.GetProfile(profile.ProfileId); @@ -206,11 +204,11 @@ namespace Vocaluxe.Base.Server newProfile.Avatar = avatar;*/ } - if (profile.PlayerName != null && profile.PlayerName != "") + if (!string.IsNullOrEmpty(profile.PlayerName)) { newProfile.PlayerName = profile.PlayerName; } - else if (newProfile.PlayerName != null && newProfile.PlayerName != "") + else if (!string.IsNullOrEmpty(newProfile.PlayerName)) { newProfile.PlayerName = "DummyName"; } @@ -237,41 +235,39 @@ namespace Vocaluxe.Base.Server return true; } - private static ProfileData[] getProfileList() + private static SProfileData[] _GetProfileList() { - List result = new List(CProfiles.NumProfiles); + List result = new List(CProfiles.NumProfiles); - foreach (CProfile profile in CProfiles.GetProfiles()) - { - result.Add(CreateProfileData(profile, true)); - } + result.AddRange(CProfiles.GetProfiles().Select(profile => _CreateProfileData(profile, true))); return result.ToArray(); } - private static ProfileData CreateProfileData(CProfile profile, bool isReadonly) + private static SProfileData _CreateProfileData(CProfile profile, bool isReadonly) { - ProfileData profileData = new ProfileData(); + SProfileData profileData = new SProfileData + { + IsEditable = !isReadonly, + ProfileId = profile.ID, + PlayerName = profile.PlayerName, + Type = (int)profile.GuestProfile, + Difficulty = (int)profile.Difficulty + }; - profileData.IsEditable = !isReadonly; - profileData.ProfileId = profile.ID; - profileData.PlayerName = profile.PlayerName; - profileData.Type = (int)profile.GuestProfile; - profileData.Difficulty = (int)profile.Difficulty; CAvatar avatar = profile.Avatar; if (avatar != null) { if (File.Exists(avatar.FileName)) { - profileData.Avatar = new Base64Image(createDelayedImage(avatar.FileName)); + profileData.Avatar = new CBase64Image(_CreateDelayedImage(avatar.FileName)); } } return profileData; } - private static CAvatar _AddAvatar(Base64Image avatarData) + private static CAvatar _AddAvatar(CBase64Image avatarData) { - string result = String.Empty; try { string filename = _SaveImage(avatarData, "snapshot", CSettings.FolderProfiles); @@ -282,10 +278,7 @@ namespace Vocaluxe.Base.Server CProfiles.AddAvatar(avatar); return avatar; } - else - { - return null; - } + return null; } catch { @@ -297,7 +290,7 @@ namespace Vocaluxe.Base.Server #region photo - private static bool sendPhoto(PhotoData photoData) + private static bool _SendPhoto(SPhotoData photoData) { if (photoData.Photo == null) { @@ -307,16 +300,16 @@ namespace Vocaluxe.Base.Server string name = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"); string filePath = _SaveImage(photoData.Photo, name, CSettings.FolderPhotos); - return (filePath != null && filePath != ""); + return !string.IsNullOrEmpty(filePath); } #endregion #region website - private static Dictionary delayedImagePath = new Dictionary(); + private static readonly Dictionary _DelayedImagePath = new Dictionary(); - private static byte[] getSiteFile(string filename) + private static byte[] _GetSiteFile(string filename) { string path = "Website/" + filename; path = path.Replace("..", ""); @@ -336,7 +329,7 @@ namespace Vocaluxe.Base.Server return File.ReadAllBytes(path); } - private static string createDelayedImage(string filename) + private static string _CreateDelayedImage(string filename) { byte[] by = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(filename)); var sb = new StringBuilder(); @@ -347,52 +340,48 @@ namespace Vocaluxe.Base.Server string hashedFilename = sb.ToString(); - if (!delayedImagePath.ContainsKey(hashedFilename)) + if (!_DelayedImagePath.ContainsKey(hashedFilename)) { - delayedImagePath.Add(hashedFilename, filename); + _DelayedImagePath.Add(hashedFilename, filename); } return hashedFilename; } - private static Base64Image getDelayedImage(string hashedFilename) + private static CBase64Image _GetDelayedImage(string hashedFilename) { - if (!delayedImagePath.ContainsKey(hashedFilename)) + if (!_DelayedImagePath.ContainsKey(hashedFilename)) { throw new FileNotFoundException("Image not found"); } - string fileName = delayedImagePath[hashedFilename]; + string fileName = _DelayedImagePath[hashedFilename]; if (File.Exists(fileName)) { Image image = Image.FromFile(fileName); - return new Base64Image(image, image.RawFormat); + return new CBase64Image(image, image.RawFormat); } - else - { - throw new FileNotFoundException("Image not found"); - } - + throw new FileNotFoundException("Image not found"); } #endregion #region songs - private static SongInfo getSong(int songId) + private static SOngInfo _GetSong(int songId) { CSong song = CSongs.GetSong(songId); - return getSongInfo(song, true); + return _GetSongInfo(song, true); } - private static SongInfo[] getAllSongs() + private static SOngInfo[] _GetAllSongs() { var songs = CSongs.Songs; return (from s in songs - select getSongInfo(s, false)).ToArray(); + select _GetSongInfo(s, false)).ToArray(); } - private static int getCurrentSongId() + private static int _GetCurrentSongId() { CSong song = CGame.GetSong(); if (song == null) @@ -402,9 +391,9 @@ namespace Vocaluxe.Base.Server return song.ID; } - private static SongInfo getSongInfo(CSong song, bool includeCover) + private static SOngInfo _GetSongInfo(CSong song, bool includeCover) { - SongInfo result = new SongInfo(); + SOngInfo result = new SOngInfo(); if (song != null) { result.Title = song.Title; @@ -416,7 +405,7 @@ namespace Vocaluxe.Base.Server result.SongId = song.ID; if (includeCover) { - result.Cover = new Base64Image(createDelayedImage(song.Folder + "\\" + song.CoverFileName)); + result.Cover = new CBase64Image(_CreateDelayedImage(song.Folder + "\\" + song.CoverFileName)); } } return result; @@ -426,7 +415,7 @@ namespace Vocaluxe.Base.Server #region user management - private static void setPassword(int profileId, string newPassword) + private static void _SetPassword(int profileId, string newPassword) { CProfile profile = CProfiles.GetProfile(profileId); if (profile == null) @@ -438,13 +427,13 @@ namespace Vocaluxe.Base.Server byte[] buffer = new byte[128]; rng.GetNonZeroBytes(buffer); byte[] salt = buffer; - byte[] hashedPassword = hash((new System.Text.UTF8Encoding()).GetBytes(newPassword), salt); + byte[] hashedPassword = _Hash((new UTF8Encoding()).GetBytes(newPassword), salt); profile.PasswordSalt = salt; profile.PasswordHash = hashedPassword; } - private static bool validatePassword(int profileId, string password) + private static bool _ValidatePassword(int profileId, string password) { CProfile profile = CProfiles.GetProfile(profileId); if (profile == null) @@ -454,21 +443,18 @@ namespace Vocaluxe.Base.Server if (profile.PasswordHash == null) { - if (password == "" || password == null) + if (string.IsNullOrEmpty(password)) { return true; //Allow emty passwords } - else - { - return false; - } + return false; } byte[] salt = profile.PasswordSalt; - return hash((new System.Text.UTF8Encoding()).GetBytes(password), salt).SequenceEqual(profile.PasswordHash); + return _Hash((new UTF8Encoding()).GetBytes(password), salt).SequenceEqual(profile.PasswordHash); } - private static bool validatePassword(int profileId, byte[] hashedPassword) + private static bool _ValidatePassword(int profileId, byte[] hashedPassword) { CProfile profile = CProfiles.GetProfile(profileId); if (profile == null) @@ -482,17 +468,14 @@ namespace Vocaluxe.Base.Server { return true; //Allow emty passwords } - else - { - return false; - } + return false; } byte[] salt = profile.PasswordSalt; return hashedPassword.SequenceEqual(profile.PasswordHash); } - private static byte[] getPassowordSalt(int profileId) + private static byte[] _GetPassowordSalt(int profileId) { CProfile profile = CProfiles.GetProfile(profileId); if (profile == null) @@ -508,7 +491,7 @@ namespace Vocaluxe.Base.Server return profile.PasswordSalt; } - private static int getUserRole(int profileId) + private static int _GetUserRole(int profileId) { CProfile profile = CProfiles.GetProfile(profileId); if (profile == null) @@ -519,7 +502,7 @@ namespace Vocaluxe.Base.Server return profile.UserRoles; } - private static void setUserRole(int profileId, int userRole) + private static void _SetUserRole(int profileId, int userRole) { CProfile profile = CProfiles.GetProfile(profileId); if (profile == null) @@ -530,12 +513,12 @@ namespace Vocaluxe.Base.Server profile.UserRoles = userRole; } - private static int getUserIdFromUsername(string username) + 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.Count() == 0) + if (!playerIds.Any()) { throw new ArgumentException("Invalid playername"); } @@ -543,7 +526,7 @@ namespace Vocaluxe.Base.Server return playerIds.First(); } - private static byte[] hash(byte[] password, byte[] salt) + private static byte[] _Hash(byte[] password, byte[] salt) { HashAlgorithm hashAlgo = new SHA256Managed(); @@ -556,13 +539,11 @@ namespace Vocaluxe.Base.Server } #endregion - - - - private static string _SaveImage(Base64Image imageDate, string name, string folder) + + private static string _SaveImage(CBase64Image imageDate, string name, string folder) { - Image avatarImage = imageDate.getImage(); - string extension = imageDate.getImageType(); + Image avatarImage = imageDate.GetImage(); + string extension = imageDate.GetImageType(); string filename = Path.Combine(folder, name); if (File.Exists(filename + "." + extension)) From bfd8672d693aa242b46a67d69450926fb21af6db Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sat, 26 Oct 2013 11:19:39 +0200 Subject: [PATCH 30/81] Webserver: Add wikipedia (artist) links to the song details pages --- Vocaluxe/Vocaluxe.csproj | 3 +++ Vocaluxe/Website/img/wikipedia.png | Bin 0 -> 2070 bytes Vocaluxe/Website/index.html | 1 + Vocaluxe/Website/js/main.js | 12 ++++++++++++ 4 files changed, 16 insertions(+) create mode 100644 Vocaluxe/Website/img/wikipedia.png diff --git a/Vocaluxe/Vocaluxe.csproj b/Vocaluxe/Vocaluxe.csproj index c008aef3..622735f7 100644 --- a/Vocaluxe/Vocaluxe.csproj +++ b/Vocaluxe/Vocaluxe.csproj @@ -358,6 +358,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Vocaluxe/Website/img/wikipedia.png b/Vocaluxe/Website/img/wikipedia.png new file mode 100644 index 0000000000000000000000000000000000000000..52f873931af83e6f8d8201d9f305a4233862b4bc GIT binary patch literal 2070 zcmV+x2PT|jjb&G>ExE-dFN=%G6wg+x)r>VZ zVr6Z^)t8%YZEf9c@9en!{e5?EaF9rWZF_sit*x)ShG&L7nqR89W&g0dyK73nfB!c5 z_3Kw6Wq)tqZEbIP1C|}^(ah|eTUlwgS-H2jmso)hX)ZS$?9p^}#z$b;{rvgU27dhb zVT!yaQDi`)QFpML0gXl@9*_Y^lr{tEfdO^@pztKs^I-&Ft;>MQbk)^;Ym$}Uzkg3G zJZ$2G8Fn*(-Wn<;S;SfU*MMoaaqX*hXyr?%g{Zd;a{n>84UC+XR5Qxw&`^#s>!n-Q?t?fub`!JZxj3ynp}R=3#{3 zVG}3JuzLfh+=mYz+LR=pKYupQVgzuPE?sh$FJE^3{rxs)b#>K!{rc6d`^(k%__%xW z_>#jdyHov;I*!F z^eRr)fjuht|7K=p+6)Lq6X_O&mQAPyfaoOZR){=}4n}6PSu=8MY|Ngi3t)+WJj*!y zlUfLCU?5{e;wXzyVe7(p?UMtGR~ zCOV8US4NDEj+z0aQZAQkgOeU9NVMo~bTB#-QPf&T_trcFX4s?g@w}Uwnrib(Cs8Em z**9W2s!;h4s=wzhU!FWzy?N5{#>)wC~7v*vjmWR4nu}LS`~5ps_ai$!JRZY zT!bjlX}CH(e*D<-8PCwEC@@8cmP#to<7uft(rxnjeB7Ndi1cA?-go0fm|>5y-jiGt zG{^#{383_Jt`tN84-*l-o_HPFpMp$@qS6kf*= z4khYA*8;*#QR_a04y_lX(9w^r-R>(+n9YE6I%~NcD)l1dId^>OfR@R@L|fENlQnr} zLku9@s2k?#D&5Pz;)EIYD3!|C$tnfB(u=SdorG4&p@e5i8(sdiDR&{FLn?92plGGj z%YNd78TKeOiUH&H6*~iTmu?qB7XUg7c@3C)J%DPfiWE0lqD8loj@IdRzm@?_V}?B% zO{M*jOwKOHO1%hkND*$Sv`n2R7{+NE>JSACVT{g0E=#AE{a}R|b~7NC8}oy$h4kG| zFQSFjrxnSgI*J(GOR4iGd%+5`889-MYBK;&{fQBpcl7l*z0-6~+9Nao_Goxy)E8dX ze&Z2t@Ta10-u_mnleCPf8#CCA%xD*ylh07*qoM6N<$f+!m9 AyZ`_I literal 0 HcmV?d00001 diff --git a/Vocaluxe/Website/index.html b/Vocaluxe/Website/index.html index 6e828e0e..06aed5fd 100644 --- a/Vocaluxe/Website/index.html +++ b/Vocaluxe/Website/index.html @@ -178,6 +178,7 @@
    diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index e2418430..c14d452f 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -246,6 +246,10 @@ function initPageLoadHandler() { $('#displaySongLinkSpotify').unbind('click').click(function () { showSpotify(result.Artist, result.Title); }); + + $('#displaySongLinkWikipedia').unbind('click').click(function () { + showWikipedia(result.Artist); + }); } else { $('#displaySongLinks').hide(); } @@ -739,4 +743,12 @@ function showSpotify(artist, title) { $("#popupVideo").popup("open"); } }); +} + +function showWikipedia(artist) { + popupVideoHeight = 800; + popupVideoWidth = 600; + + $("#popupVideo iframe").attr("src", "http://m.wikipedia.org/wiki/Special:Search/" + artist); + $("#popupVideo").popup("open"); } \ No newline at end of file From 944c1b0771ea6d7c104b4dbcc7f64399d97a06d6 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sat, 26 Oct 2013 11:29:39 +0200 Subject: [PATCH 31/81] Webserver: some fixes --- ClientServerLib/ClientServerLib/CWebservice.cs | 4 ++-- Vocaluxe/Base/Server/CVocaluxeServer.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs index 6b54e961..5e3db8cb 100644 --- a/ClientServerLib/ClientServerLib/CWebservice.cs +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -259,8 +259,6 @@ namespace ServerLib return; } - CServer.SendProfileData(profile); - if (!string.IsNullOrEmpty(profile.Password)) { int profileId = profile.ProfileId; @@ -271,6 +269,8 @@ namespace ServerLib CServer.SetPassword(profileId, profile.Password); } + + CServer.SendProfileData(profile); } public SProfileData GetProfile(int profileId) diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index 45340056..645075db 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -85,7 +85,7 @@ namespace Vocaluxe.Base.Server private static bool _SendKeyEvent(string key) { bool result = false; - if (key != null && key != "") + if (!string.IsNullOrEmpty(key)) { switch (key.ToLower()) { From dc54d0520271b272aaa9733568fecb3e669071ff Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sat, 26 Oct 2013 11:33:11 +0200 Subject: [PATCH 32/81] Webserver: split CWebservice and ICWebservice into two files --- .../ClientServerLib/CWebservice.cs | 133 ----------------- .../ClientServerLib/ICWebservice.cs | 140 ++++++++++++++++++ .../ClientServerLib/ServerLib.csproj | 1 + 3 files changed, 141 insertions(+), 133 deletions(-) create mode 100644 ClientServerLib/ClientServerLib/ICWebservice.cs diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs index 5e3db8cb..15b3dc8b 100644 --- a/ClientServerLib/ClientServerLib/CWebservice.cs +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -6,139 +6,6 @@ using System.ServiceModel.Channels; 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 = "/delayedImage?id={id}")] - CBase64Image GetDelayedImage(String id); - - #endregion - - #region songs - - [OperationContract] - [WebInvoke(Method = "GET", - ResponseFormat = WebMessageFormat.Json, - UriTemplate = "/getSong?songId={songId}")] - SOngInfo GetSong(int songId); - - [OperationContract] - [WebInvoke(Method = "GET", - ResponseFormat = WebMessageFormat.Json, - UriTemplate = "/getCurrentSongId")] - int GetCurrentSongId(); - - [OperationContract] - [WebInvoke(Method = "GET", - ResponseFormat = WebMessageFormat.Json, - UriTemplate = "/getAllSongs")] - SOngInfo[] GetAllSongs(); - - #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); - - #endregion - } - class CWebservice : ICWebservice { private static Guid _GetSession() diff --git a/ClientServerLib/ClientServerLib/ICWebservice.cs b/ClientServerLib/ClientServerLib/ICWebservice.cs new file mode 100644 index 00000000..f1e8b398 --- /dev/null +++ b/ClientServerLib/ClientServerLib/ICWebservice.cs @@ -0,0 +1,140 @@ +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 = "/delayedImage?id={id}")] + CBase64Image GetDelayedImage(String id); + + #endregion + + #region songs + + [OperationContract] + [WebInvoke(Method = "GET", + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/getSong?songId={songId}")] + SOngInfo GetSong(int songId); + + [OperationContract] + [WebInvoke(Method = "GET", + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/getCurrentSongId")] + int GetCurrentSongId(); + + [OperationContract] + [WebInvoke(Method = "GET", + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/getAllSongs")] + SOngInfo[] GetAllSongs(); + + #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); + + #endregion + } +} \ No newline at end of file diff --git a/ClientServerLib/ClientServerLib/ServerLib.csproj b/ClientServerLib/ClientServerLib/ServerLib.csproj index 417c9063..3a00f689 100644 --- a/ClientServerLib/ClientServerLib/ServerLib.csproj +++ b/ClientServerLib/ClientServerLib/ServerLib.csproj @@ -51,6 +51,7 @@ + From 3d55da59a3bb110bdb7ba058b202fbb664e07a3e Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sat, 26 Oct 2013 14:36:38 +0200 Subject: [PATCH 33/81] Webserver: Add methode for getting photolinks of a round --- Vocaluxe/Base/Server/CVocaluxeServer.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index 645075db..2da17154 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -25,6 +25,7 @@ using System.Windows.Forms; using ServerLib; using Vocaluxe.Lib.Input; using VocaluxeLib; +using VocaluxeLib.Draw; using VocaluxeLib.Profile; using VocaluxeLib.Songs; using System.Security.Cryptography; @@ -290,6 +291,8 @@ namespace Vocaluxe.Base.Server #region photo + private static List photosOfThisRound = new List(); + private static bool _SendPhoto(SPhotoData photoData) { if (photoData.Photo == null) @@ -299,8 +302,20 @@ namespace Vocaluxe.Base.Server 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; + } - return !string.IsNullOrEmpty(filePath); + internal static string[] getPhotosOfThisRound() + { + var result = photosOfThisRound.ToArray(); + photosOfThisRound.Clear(); + return result; } #endregion From a9902cf1eff702c260d927888d41c22c6f31f102 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 27 Oct 2013 12:47:13 +0100 Subject: [PATCH 34/81] Removed "Release" and "Debug" Configs --- Vocaluxe.sln | 54 ---------------------------------------------------- 1 file changed, 54 deletions(-) diff --git a/Vocaluxe.sln b/Vocaluxe.sln index c7d86e44..05ef3948 100644 --- a/Vocaluxe.sln +++ b/Vocaluxe.sln @@ -102,13 +102,6 @@ Global {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.Debug|Any CPU.ActiveCfg = DebugWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.Debug|Mixed Platforms.ActiveCfg = DebugWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.Debug|Mixed Platforms.Build.0 = DebugWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.Debug|x64.ActiveCfg = DebugWin|x64 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.Debug|x64.Build.0 = DebugWin|x64 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.Debug|x86.ActiveCfg = DebugWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.Debug|x86.Build.0 = DebugWin|x86 {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|Any CPU.ActiveCfg = DebugLinux|x86 {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|Mixed Platforms.ActiveCfg = DebugLinux|x86 {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|Mixed Platforms.Build.0 = DebugLinux|x86 @@ -123,13 +116,6 @@ 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}.Release|Any CPU.ActiveCfg = ReleaseWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.Release|Mixed Platforms.ActiveCfg = ReleaseWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.Release|Mixed Platforms.Build.0 = ReleaseWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.Release|x64.ActiveCfg = ReleaseWin|x64 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.Release|x64.Build.0 = ReleaseWin|x64 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.Release|x86.ActiveCfg = ReleaseWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.Release|x86.Build.0 = ReleaseWin|x86 {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|Any CPU.ActiveCfg = ReleaseLinux|x86 {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|Mixed Platforms.ActiveCfg = ReleaseLinux|x86 {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|Mixed Platforms.Build.0 = ReleaseLinux|x86 @@ -144,13 +130,6 @@ Global {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.Debug|Any CPU.ActiveCfg = DebugWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.Debug|Mixed Platforms.ActiveCfg = DebugWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.Debug|Mixed Platforms.Build.0 = DebugWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.Debug|x64.ActiveCfg = DebugWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.Debug|x64.Build.0 = DebugWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.Debug|x86.ActiveCfg = DebugWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.Debug|x86.Build.0 = DebugWin|x86 {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|Any CPU.ActiveCfg = DebugLinux|x86 {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|Mixed Platforms.ActiveCfg = DebugLinux|x86 {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|Mixed Platforms.Build.0 = DebugLinux|x86 @@ -165,13 +144,6 @@ 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}.Release|Any CPU.ActiveCfg = ReleaseWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.Release|Mixed Platforms.ActiveCfg = ReleaseWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.Release|Mixed Platforms.Build.0 = ReleaseWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.Release|x64.ActiveCfg = ReleaseWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.Release|x64.Build.0 = ReleaseWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.Release|x86.ActiveCfg = ReleaseWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.Release|x86.Build.0 = ReleaseWin|x86 {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|Any CPU.ActiveCfg = ReleaseLinux|x86 {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|Mixed Platforms.ActiveCfg = ReleaseLinux|x86 {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|Mixed Platforms.Build.0 = ReleaseLinux|x86 @@ -186,13 +158,6 @@ Global {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {ED007796-367F-4142-AA55-5450C7645C2C}.Debug|Any CPU.ActiveCfg = DebugWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.Debug|Mixed Platforms.ActiveCfg = DebugWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.Debug|Mixed Platforms.Build.0 = DebugWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.Debug|x64.ActiveCfg = DebugWin|x64 - {ED007796-367F-4142-AA55-5450C7645C2C}.Debug|x64.Build.0 = DebugWin|x64 - {ED007796-367F-4142-AA55-5450C7645C2C}.Debug|x86.ActiveCfg = DebugWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.Debug|x86.Build.0 = DebugWin|Win32 {ED007796-367F-4142-AA55-5450C7645C2C}.DebugLinux|Any CPU.ActiveCfg = DebugWin|Win32 {ED007796-367F-4142-AA55-5450C7645C2C}.DebugLinux|Mixed Platforms.ActiveCfg = DebugWin|Win32 {ED007796-367F-4142-AA55-5450C7645C2C}.DebugLinux|Mixed Platforms.Build.0 = DebugWin|Win32 @@ -205,13 +170,6 @@ 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}.Release|Any CPU.ActiveCfg = ReleaseWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.Release|Mixed Platforms.ActiveCfg = ReleaseWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.Release|Mixed Platforms.Build.0 = ReleaseWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.Release|x64.ActiveCfg = ReleaseWin|x64 - {ED007796-367F-4142-AA55-5450C7645C2C}.Release|x64.Build.0 = ReleaseWin|x64 - {ED007796-367F-4142-AA55-5450C7645C2C}.Release|x86.ActiveCfg = ReleaseWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.Release|x86.Build.0 = ReleaseWin|Win32 {ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseLinux|Any CPU.ActiveCfg = ReleaseWin|Win32 {ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseLinux|Mixed Platforms.ActiveCfg = ReleaseWin|Win32 {ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseLinux|Mixed Platforms.Build.0 = ReleaseWin|Win32 @@ -224,12 +182,6 @@ Global {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}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Debug|x64.ActiveCfg = Debug|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Debug|x86.ActiveCfg = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|Any CPU.ActiveCfg = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|Any CPU.Build.0 = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -242,12 +194,6 @@ Global {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|Mixed Platforms.Build.0 = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|x64.ActiveCfg = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|x86.ActiveCfg = Debug|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Release|Any CPU.Build.0 = Release|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Release|x64.ActiveCfg = Release|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.Release|x86.ActiveCfg = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|Any CPU.ActiveCfg = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|Any CPU.Build.0 = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|Mixed Platforms.ActiveCfg = Release|Any CPU From 4992a4ca6f46de6711353b8589146e45a0537b65 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 27 Oct 2013 12:50:44 +0100 Subject: [PATCH 35/81] ClientServerLib.dll is generated automatically --- Output/ClientServerLib.dll | Bin 50688 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Output/ClientServerLib.dll diff --git a/Output/ClientServerLib.dll b/Output/ClientServerLib.dll deleted file mode 100644 index 8a30dec5e8e5f512140264b571843a090bfda90c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50688 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 JeJy@wflrjlUtItI From ee3f5241090eb205aff9153aadb569905f1d1cca Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 27 Oct 2013 12:52:54 +0100 Subject: [PATCH 36/81] ClientServerLib.dll is generated automatically - ignore it --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 01c68b74..f89e714b 100644 --- a/.gitignore +++ b/.gitignore @@ -52,5 +52,6 @@ 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 From 15a4e312edac2527ec013397dc1256fad164bdb2 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 27 Oct 2013 13:27:15 +0100 Subject: [PATCH 37/81] Webserver: Fixed autologut bug with createprofile --- Vocaluxe/Website/js/main.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index c14d452f..924b8b85 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -578,6 +578,11 @@ function logout() { } function checkSession() { + if (ownProfileId == -1 + && profileIdRequest == -1 + && ($.mobile.activePage.attr("id") == "displayProfile" || $.mobile.activePage.attr("id") == "login")) { + return; + } request({ url: "getOwnProfileId" }).done(function (result) { From 1ac6d0c119ef041b75cea3e48c7de4ce306fd4f0 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 27 Oct 2013 13:28:53 +0100 Subject: [PATCH 38/81] Corrected BuildDependencies (something went wrong here) --- Vocaluxe.sln | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Vocaluxe.sln b/Vocaluxe.sln index 05ef3948..16d994af 100644 --- a/Vocaluxe.sln +++ b/Vocaluxe.sln @@ -3,6 +3,7 @@ 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} @@ -64,6 +65,7 @@ Global {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x86.ActiveCfg = DebugLinux|x86 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x86.Build.0 = DebugLinux|x86 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|Any CPU.Build.0 = DebugWin|x86 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|Mixed Platforms.ActiveCfg = DebugWin|x86 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|Mixed Platforms.Build.0 = DebugWin|x86 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x64.ActiveCfg = DebugWin|x64 From 5432676c08006f6c3c6c7b82411722c77960249c Mon Sep 17 00:00:00 2001 From: lukeIam Date: Tue, 29 Oct 2013 11:20:58 +0100 Subject: [PATCH 39/81] Webserver: Typo --- ClientServerLib/ClientServerLib/DataStructs.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ClientServerLib/ClientServerLib/DataStructs.cs b/ClientServerLib/ClientServerLib/DataStructs.cs index 8eba693d..0a33dd7b 100644 --- a/ClientServerLib/ClientServerLib/DataStructs.cs +++ b/ClientServerLib/ClientServerLib/DataStructs.cs @@ -103,14 +103,14 @@ namespace ServerLib #region songs - public delegate SOngInfo GetSongDelegate(int songId); + public delegate SSongInfo GetSongDelegate(int songId); - public delegate SOngInfo[] GetAllSongsDelegate(); + public delegate SSongInfo[] GetAllSongsDelegate(); public delegate int GetCurrentSongIdDelegate(); [DataContract] - public struct SOngInfo + public struct SSongInfo { [DataMember] public string Title; From c782ba38627deb36bde74347aaddc873554e02d1 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Tue, 29 Oct 2013 14:39:47 +0100 Subject: [PATCH 40/81] Webserver: Edit profiles (server part) --- ClientServerLib/ClientServerLib/CServer.cs | 58 ++++++- .../ClientServerLib/CWebservice.cs | 88 ++++++++++- .../ClientServerLib/DataStructs.cs | 38 +++++ .../ClientServerLib/ICWebservice.cs | 55 ++++++- ClientServerLib/ClientServerLib/UserRights.cs | 4 +- Vocaluxe/Base/Server/CVocaluxeServer.cs | 144 +++++++++++++++++- 6 files changed, 371 insertions(+), 16 deletions(-) diff --git a/ClientServerLib/ClientServerLib/CServer.cs b/ClientServerLib/ClientServerLib/CServer.cs index 59d9e173..d115d11f 100644 --- a/ClientServerLib/ClientServerLib/CServer.cs +++ b/ClientServerLib/ClientServerLib/CServer.cs @@ -96,6 +96,60 @@ namespace ServerLib } + #endregion + + #region playlist + + private static GetPlaylistsDelegate _GetPlaylists; + public static GetPlaylistsDelegate GetPlaylists + { + get { return _GetPlaylists; } + set { _GetPlaylists = value; } + } + + + private static GetPlaylistDelegate _GetPlaylist; + public static GetPlaylistDelegate GetPlaylist + { + get { return _GetPlaylist; } + set { _GetPlaylist = value; } + } + + private static AddSongToPlaylistDelegate _AddSongToPlaylist; + public static AddSongToPlaylistDelegate AddSongToPlaylist + { + get { return _AddSongToPlaylist; } + set { _AddSongToPlaylist = value; } + } + + private static RemoveSongFromPlaylistDelegate _RemoveSongFromPlaylist; + public static RemoveSongFromPlaylistDelegate RemoveSongFromPlaylist + { + get { return _RemoveSongFromPlaylist; } + set { _RemoveSongFromPlaylist = value; } + } + + private static MoveSongInPlaylistDelegate _MoveSongInPlaylist; + public static MoveSongInPlaylistDelegate MoveSongInPlaylist + { + get { return _MoveSongInPlaylist; } + set { _MoveSongInPlaylist = value; } + } + + private static PlaylistContainsSongDelegate _PlaylistContainsSong; + public static PlaylistContainsSongDelegate PlaylistContainsSong + { + get { return _PlaylistContainsSong; } + set { _PlaylistContainsSong = value; } + } + + private static GetPlaylistSongsDelegate _GetPlaylistSongs; + public static GetPlaylistSongsDelegate GetPlaylistSongs + { + get { return _GetPlaylistSongs; } + set { _GetPlaylistSongs = value; } + } + #endregion #region user management @@ -135,8 +189,8 @@ namespace ServerLib set { CServer._GetUserIdFromUsername = value; } } - #endregion + #endregion public CServer(int port, bool encrypted) { _Init(port, encrypted); @@ -163,7 +217,7 @@ namespace ServerLib MaxReceivedMessageSize = 10485760, MaxBufferSize = 10485760, MaxBufferPoolSize = 10485760, - ReaderQuotas = {MaxStringContentLength = 10485760, MaxArrayLength = 10485760, MaxBytesPerRead = 10485760} + ReaderQuotas = { MaxStringContentLength = 10485760, MaxArrayLength = 10485760, MaxBytesPerRead = 10485760 } }; if (encrypted) { diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs index 15b3dc8b..cd39312f 100644 --- a/ClientServerLib/ClientServerLib/CWebservice.cs +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -333,7 +333,7 @@ namespace ServerLib #region songs - public SOngInfo GetSong(int songId) + public SSongInfo GetSong(int songId) { return CServer.GetSong(songId); } @@ -343,11 +343,63 @@ namespace ServerLib return CServer.GetCurrentSongId(); } - public SOngInfo[] GetAllSongs() + 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)||_CheckRight(EUserRights.EditPlaylists)) + { + CServer.AddSongToPlaylist(songId, playlistId, allowDuplicates); + } + } + + public void RemoveSongFromPlaylist(int position, int playlistId, int songId) + { + if (_CheckRight(EUserRights.EditPlaylists)) + { + CServer.RemoveSongFromPlaylist(position, playlistId, songId); + } + } + + public void MoveSongInPlaylist(int oldPosition, int newPosition, int playlistId, int songId) + { + if (_CheckRight(EUserRights.EditPlaylists)) + { + CServer.MoveSongInPlaylist(oldPosition, 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 bool IsPlaylistEditable(int playlistId) + { + return _CheckRight(EUserRights.EditPlaylists); + } + #endregion #region user management @@ -362,7 +414,8 @@ namespace ServerLib Guid sessionKey = _GetSession(); if (sessionKey == Guid.Empty) { - if (WebOperationContext.Current != null) { + if (WebOperationContext.Current != null) + { WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; } @@ -370,7 +423,8 @@ namespace ServerLib } if (!CSessionControl.RequestRight(sessionKey, EUserRights.EditAllProfiles)) { - if (WebOperationContext.Current != null) { + if (WebOperationContext.Current != null) + { WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; } @@ -379,6 +433,32 @@ namespace ServerLib CServer.SetUserRole(profileId, userRole); } + 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; + } + #endregion } } diff --git a/ClientServerLib/ClientServerLib/DataStructs.cs b/ClientServerLib/ClientServerLib/DataStructs.cs index 0a33dd7b..298fbba1 100644 --- a/ClientServerLib/ClientServerLib/DataStructs.cs +++ b/ClientServerLib/ClientServerLib/DataStructs.cs @@ -109,6 +109,20 @@ namespace ServerLib public delegate int GetCurrentSongIdDelegate(); + 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 oldPosition, int newPosition, int playlistId, int songId); + + public delegate bool PlaylistContainsSongDelegate(int songId, int playlistId); + + public delegate SPlaylistSongInfo[] GetPlaylistSongsDelegate(int playlistId); + [DataContract] public struct SSongInfo { @@ -130,6 +144,30 @@ namespace ServerLib public int SongId { get; set; } } + public struct SPlaylistSongInfo + { + [DataMember] + public SSongInfo Song; + [DataMember] + public int PlaylistId; + [DataMember] + public int PlaylistPosition; + [DataMember] + public int GameMode; + } + + public struct SPlaylistInfo + { + [DataMember] + public int PlaylistId; + [DataMember] + public string PlaylistName; + [DataMember] + public int SongCount; + [DataMember] + public string LastChanged; + } + #endregion #region user management diff --git a/ClientServerLib/ClientServerLib/ICWebservice.cs b/ClientServerLib/ClientServerLib/ICWebservice.cs index f1e8b398..3a6e3326 100644 --- a/ClientServerLib/ClientServerLib/ICWebservice.cs +++ b/ClientServerLib/ClientServerLib/ICWebservice.cs @@ -105,7 +105,7 @@ namespace ServerLib [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/getSong?songId={songId}")] - SOngInfo GetSong(int songId); + SSongInfo GetSong(int songId); [OperationContract] [WebInvoke(Method = "GET", @@ -117,7 +117,58 @@ namespace ServerLib [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/getAllSongs")] - SOngInfo[] 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?oldPosition={oldPosition}&newPosition={newPosition}&playlistId={playlistId}&songId={songId}")] + void MoveSongInPlaylist(int oldPosition, 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 = "/isPlaylistEditable?playlistId={playlistId}")] + bool IsPlaylistEditable(int playlistId); #endregion diff --git a/ClientServerLib/ClientServerLib/UserRights.cs b/ClientServerLib/ClientServerLib/UserRights.cs index 3d02b056..14c874f0 100644 --- a/ClientServerLib/ClientServerLib/UserRights.cs +++ b/ClientServerLib/ClientServerLib/UserRights.cs @@ -9,6 +9,8 @@ namespace ServerLib EditAllProfiles = 0x01, UploadPhotos = 0x02, ViewOtherProfiles = 0x04, - UseKeyboard = 0x08 + UseKeyboard = 0x08, + EditPlaylists = 0x16, + AddSongToPlaylist = 0x32 } } diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index 2da17154..cfaf864e 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -24,8 +24,10 @@ using System.Text; using System.Windows.Forms; 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; @@ -307,7 +309,7 @@ namespace Vocaluxe.Base.Server photosOfThisRound.Add(filePath); return true; } - + return false; } @@ -383,17 +385,17 @@ namespace Vocaluxe.Base.Server #region songs - private static SOngInfo _GetSong(int songId) + private static SSongInfo _GetSong(int songId) { CSong song = CSongs.GetSong(songId); return _GetSongInfo(song, true); } - private static SOngInfo[] _GetAllSongs() + private static SSongInfo[] _GetAllSongs() { var songs = CSongs.Songs; return (from s in songs - select _GetSongInfo(s, false)).ToArray(); + select _GetSongInfo(s, false)).ToArray(); } private static int _GetCurrentSongId() @@ -406,9 +408,9 @@ namespace Vocaluxe.Base.Server return song.ID; } - private static SOngInfo _GetSongInfo(CSong song, bool includeCover) + private static SSongInfo _GetSongInfo(CSong song, bool includeCover) { - SOngInfo result = new SOngInfo(); + SSongInfo result = new SSongInfo(); if (song != null) { result.Title = song.Title; @@ -428,6 +430,134 @@ namespace Vocaluxe.Base.Server #endregion + #region playlist + + public static SPlaylistInfo[] GetPlaylists() + { + return (from p in CPlaylists.Playlists + select _GetPlaylistInfo(p)).ToArray(); + } + + public static SPlaylistInfo GetPlaylist(int playlistId) + { + if (CPlaylists.Playlists.Length <= playlistId) + { + throw new ArgumentException("invalid playlistId"); + } + return _GetPlaylistInfo(CPlaylists.Playlists[playlistId]); + } + + public static void AddSongToPlaylist(int songId, int playlistId, bool allowDuplicates) + { + if (CPlaylists.Playlists.Length <= playlistId) + { + throw new ArgumentException("invalid playlistId"); + } + + if (allowDuplicates || PlaylistContainsSong(songId, playlistId)) + { + CPlaylists.AddPlaylistSong(playlistId, songId); + } + else + { + throw new ArgumentException("song exists in this playlist"); + } + } + + public static void RemoveSongFromPlaylist(int position, int playlistId, int songId) + { + if (CPlaylists.Playlists.Length <= playlistId) + { + throw new ArgumentException("invalid playlistId"); + } + if (!PlaylistContainsSong(songId, playlistId)) + { + throw new ArgumentException("invalid songId"); + } + if (CPlaylists.Playlists[playlistId].Songs.Count <= position || CPlaylists.Playlists[playlistId].Songs[position].SongID != songId) + { + throw new ArgumentException("invalid position"); + } + CPlaylists.Playlists[playlistId].DeleteSong(position); + } + + public static void MoveSongInPlaylist(int oldPosition, int newPosition, int playlistId, int songId) + { + if (CPlaylists.Playlists.Length <= playlistId) + { + throw new ArgumentException("invalid playlistId"); + } + if (!PlaylistContainsSong(songId, playlistId)) + { + throw new ArgumentException("invalid songId"); + } + if (CPlaylists.Playlists[playlistId].Songs.Count <= oldPosition || CPlaylists.Playlists[playlistId].Songs[oldPosition].SongID != songId) + { + throw new ArgumentException("invalid oldPosition"); + } + if (CPlaylists.Playlists[playlistId].Songs.Count < newPosition ) + { + throw new ArgumentException("invalid newPosition"); + } + + CPlaylists.MovePlaylistSong(playlistId,oldPosition, newPosition); + } + + public static bool PlaylistContainsSong(int songId, int playlistId) + { + if (CPlaylists.Playlists.Length <= playlistId) + { + throw new ArgumentException("invalid playlistId"); + } + return CPlaylists.Playlists[playlistId].Songs.Any(s => s.SongID == songId); + } + + public static SPlaylistSongInfo[] GetPlaylistSongs(int playlistId) + { + if (CPlaylists.Playlists.Length <= playlistId) + { + 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], 1 /*TODO:PlaylistID???*/, i); + } + return result; + } + + private static SPlaylistInfo _GetPlaylistInfo(CPlaylistFile playlist) + { + return new SPlaylistInfo + { + PlaylistId = 1, /*TODO: PlaylistId*/ + PlaylistName = playlist.PlaylistName, + SongCount = playlist.Songs.Count, + LastChanged = DateTime.Now.ToLongDateString() + }; + } + + #endregion + #region user management private static void _SetPassword(int profileId, string newPassword) @@ -554,7 +684,7 @@ namespace Vocaluxe.Base.Server } #endregion - + private static string _SaveImage(CBase64Image imageDate, string name, string folder) { Image avatarImage = imageDate.GetImage(); From 959a11a4a2d43bcbe024067cfda5f616b0932892 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Tue, 29 Oct 2013 14:56:55 +0100 Subject: [PATCH 41/81] Webserver: use a methode for checking rights --- .../ClientServerLib/CWebservice.cs | 118 +++--------------- 1 file changed, 20 insertions(+), 98 deletions(-) diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs index cd39312f..d5d63d70 100644 --- a/ClientServerLib/ClientServerLib/CWebservice.cs +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -29,25 +29,12 @@ namespace ServerLib public void SendKeyEvent(string key) { - Guid sessionKey = _GetSession(); + if (!_CheckRight(EUserRights.UseKeyboard)) + { + return; + } - if (sessionKey == Guid.Empty) - { - if (WebOperationContext.Current != null) - { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; - } - } - else if (!CSessionControl.RequestRight(sessionKey, EUserRights.UseKeyboard)) - { - if (WebOperationContext.Current != null) - { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; - } - } - else if (CServer.SendKeyEvent == null) + if (CServer.SendKeyEvent == null) { if (WebOperationContext.Current != null) { @@ -94,24 +81,8 @@ namespace ServerLib if (profile.ProfileId != -1) //-1 is the id for a new profile { - if (sessionKey == Guid.Empty) + if (!(_CheckRight(EUserRights.EditAllProfiles) || CSessionControl.GetUserIdFromSession(sessionKey) == profile.ProfileId)) { - if (WebOperationContext.Current != null) - { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; - } - return; - } - - if (!CSessionControl.RequestRight(sessionKey, EUserRights.EditAllProfiles) && - CSessionControl.GetUserIdFromSession(sessionKey) != profile.ProfileId) - { - if (WebOperationContext.Current != null) - { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; - } return; } } @@ -143,37 +114,22 @@ namespace ServerLib public SProfileData GetProfile(int profileId) { Guid sessionKey = _GetSession(); - - if (sessionKey == Guid.Empty) + if (_CheckRight(EUserRights.ViewOtherProfiles) || CSessionControl.GetUserIdFromSession(sessionKey) == profileId) { - if (WebOperationContext.Current != null) + if (CServer.GetProfileData == null) { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; + return new SProfileData(); } - return new SProfileData(); - } - if (!CSessionControl.RequestRight(sessionKey, EUserRights.ViewOtherProfiles) && - CSessionControl.GetUserIdFromSession(sessionKey) != profileId) - { - if (WebOperationContext.Current != null) - { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; - } - return new SProfileData(); - } + bool isReadonly = (!CSessionControl.RequestRight(sessionKey, EUserRights.EditAllProfiles) && + CSessionControl.GetUserIdFromSession(sessionKey) != profileId); - if (CServer.GetProfileData == null) + return CServer.GetProfileData(profileId, isReadonly); + } + else { return new SProfileData(); } - - bool isReadonly = (!CSessionControl.RequestRight(sessionKey, EUserRights.EditAllProfiles) && - CSessionControl.GetUserIdFromSession(sessionKey) != profileId); - - return CServer.GetProfileData(profileId, isReadonly); } public SProfileData[] GetProfileList() @@ -191,28 +147,10 @@ namespace ServerLib public void SendPhoto(SPhotoData photo) { - Guid sessionKey = _GetSession(); - if (sessionKey == Guid.Empty) + if (_CheckRight(EUserRights.UploadPhotos)) { - if (WebOperationContext.Current != null) - { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; - } - return; + CServer.SendPhoto(photo); } - - if (!CSessionControl.RequestRight(sessionKey, EUserRights.UploadPhotos)) - { - if (WebOperationContext.Current != null) - { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; - } - return; - } - - CServer.SendPhoto(photo); } #endregion @@ -363,7 +301,7 @@ namespace ServerLib public void AddSongToPlaylist(int songId, int playlistId, bool allowDuplicates) { - if (_CheckRight(EUserRights.AddSongToPlaylist)||_CheckRight(EUserRights.EditPlaylists)) + if (_CheckRight(EUserRights.AddSongToPlaylist) || _CheckRight(EUserRights.EditPlaylists)) { CServer.AddSongToPlaylist(songId, playlistId, allowDuplicates); } @@ -399,7 +337,7 @@ namespace ServerLib { return _CheckRight(EUserRights.EditPlaylists); } - + #endregion #region user management @@ -411,26 +349,10 @@ namespace ServerLib public void SetUserRole(int profileId, int userRole) { - Guid sessionKey = _GetSession(); - if (sessionKey == Guid.Empty) + if (_CheckRight(EUserRights.EditAllProfiles)) { - if (WebOperationContext.Current != null) - { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "No session"; - } - return; + CServer.SetUserRole(profileId, userRole); } - if (!CSessionControl.RequestRight(sessionKey, EUserRights.EditAllProfiles)) - { - if (WebOperationContext.Current != null) - { - WebOperationContext.Current.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.Forbidden; - WebOperationContext.Current.OutgoingResponse.StatusDescription = "Not allowed"; - } - return; - } - CServer.SetUserRole(profileId, userRole); } private static bool _CheckRight(EUserRights requestedRight) From 35657f8698bf3c54a3dcd3a403e6de41b6e3449a Mon Sep 17 00:00:00 2001 From: lukeIam Date: Fri, 8 Nov 2013 22:44:30 +0100 Subject: [PATCH 42/81] Webserver: - Create/edit/delete playlists in the app - Fixed projektconfiguration (some project builds were disabled) - hide menue lines if the user has no right --- ClientServerLib/ClientServerLib/CServer.cs | 36 ++- .../ClientServerLib/CWebservice.cs | 32 +- .../ClientServerLib/DataStructs.cs | 40 ++- .../ClientServerLib/ICWebservice.cs | 21 +- ClientServerLib/ClientServerLib/UserRights.cs | 7 +- .../ClientServerLib/UserRoleControl.cs | 9 +- Vocaluxe.sln | 6 + Vocaluxe/Base/CConfig.cs | 8 +- Vocaluxe/Base/CPlaylists.cs | 28 +- Vocaluxe/Base/Server/CVocaluxeServer.cs | 80 +++-- Vocaluxe/Lib/Playlist/CPlaylistFile.cs | 30 +- Vocaluxe/Vocaluxe.csproj | 12 + Vocaluxe/Website/css/style.css | 13 +- Vocaluxe/Website/img/addPlaylist.png | Bin 0 -> 3760 bytes Vocaluxe/Website/img/playlists.png | Bin 0 -> 29197 bytes Vocaluxe/Website/index.html | 54 +++- .../Website/js/jquery-ui-1.10.3.custom.min.js | 6 + .../Website/js/jquery.ui.touch-punch.min.js | 11 + Vocaluxe/Website/js/main.js | 292 +++++++++++++++++- 19 files changed, 572 insertions(+), 113 deletions(-) create mode 100644 Vocaluxe/Website/img/addPlaylist.png create mode 100644 Vocaluxe/Website/img/playlists.png create mode 100644 Vocaluxe/Website/js/jquery-ui-1.10.3.custom.min.js create mode 100644 Vocaluxe/Website/js/jquery.ui.touch-punch.min.js diff --git a/ClientServerLib/ClientServerLib/CServer.cs b/ClientServerLib/ClientServerLib/CServer.cs index d115d11f..d2ef677d 100644 --- a/ClientServerLib/ClientServerLib/CServer.cs +++ b/ClientServerLib/ClientServerLib/CServer.cs @@ -84,14 +84,14 @@ namespace ServerLib private static GetAllSongsDelegate _GetAllSongs; public static GetAllSongsDelegate GetAllSongs { - get { return CServer._GetAllSongs; } + internal get { return CServer._GetAllSongs; } set { CServer._GetAllSongs = value; } } private static GetCurrentSongIdDelegate _GetCurrentSongId; public static GetCurrentSongIdDelegate GetCurrentSongId { - get { return CServer._GetCurrentSongId; } + internal get { return CServer._GetCurrentSongId; } set { CServer._GetCurrentSongId = value; } } @@ -103,7 +103,7 @@ namespace ServerLib private static GetPlaylistsDelegate _GetPlaylists; public static GetPlaylistsDelegate GetPlaylists { - get { return _GetPlaylists; } + internal get { return _GetPlaylists; } set { _GetPlaylists = value; } } @@ -111,45 +111,59 @@ namespace ServerLib private static GetPlaylistDelegate _GetPlaylist; public static GetPlaylistDelegate GetPlaylist { - get { return _GetPlaylist; } + internal get { return _GetPlaylist; } set { _GetPlaylist = value; } } private static AddSongToPlaylistDelegate _AddSongToPlaylist; public static AddSongToPlaylistDelegate AddSongToPlaylist { - get { return _AddSongToPlaylist; } + internal get { return _AddSongToPlaylist; } set { _AddSongToPlaylist = value; } } private static RemoveSongFromPlaylistDelegate _RemoveSongFromPlaylist; public static RemoveSongFromPlaylistDelegate RemoveSongFromPlaylist { - get { return _RemoveSongFromPlaylist; } + internal get { return _RemoveSongFromPlaylist; } set { _RemoveSongFromPlaylist = value; } } private static MoveSongInPlaylistDelegate _MoveSongInPlaylist; public static MoveSongInPlaylistDelegate MoveSongInPlaylist { - get { return _MoveSongInPlaylist; } + internal get { return _MoveSongInPlaylist; } set { _MoveSongInPlaylist = value; } } private static PlaylistContainsSongDelegate _PlaylistContainsSong; public static PlaylistContainsSongDelegate PlaylistContainsSong { - get { return _PlaylistContainsSong; } + internal get { return _PlaylistContainsSong; } set { _PlaylistContainsSong = value; } } private static GetPlaylistSongsDelegate _GetPlaylistSongs; public static GetPlaylistSongsDelegate GetPlaylistSongs { - get { return _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 @@ -188,9 +202,9 @@ namespace ServerLib internal get { return CServer._GetUserIdFromUsername; } set { CServer._GetUserIdFromUsername = value; } } - - + #endregion + public CServer(int port, bool encrypted) { _Init(port, encrypted); diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs index d5d63d70..15990d3c 100644 --- a/ClientServerLib/ClientServerLib/CWebservice.cs +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -301,7 +301,7 @@ namespace ServerLib public void AddSongToPlaylist(int songId, int playlistId, bool allowDuplicates) { - if (_CheckRight(EUserRights.AddSongToPlaylist) || _CheckRight(EUserRights.EditPlaylists)) + if (_CheckRight(EUserRights.AddSongToPlaylist)) { CServer.AddSongToPlaylist(songId, playlistId, allowDuplicates); } @@ -309,17 +309,17 @@ namespace ServerLib public void RemoveSongFromPlaylist(int position, int playlistId, int songId) { - if (_CheckRight(EUserRights.EditPlaylists)) + if (_CheckRight(EUserRights.RemoveSongsFromPlaylists)) { CServer.RemoveSongFromPlaylist(position, playlistId, songId); } } - public void MoveSongInPlaylist(int oldPosition, int newPosition, int playlistId, int songId) + public void MoveSongInPlaylist(int newPosition, int playlistId, int songId) { - if (_CheckRight(EUserRights.EditPlaylists)) + if (_CheckRight(EUserRights.ReorderPlaylists)) { - CServer.MoveSongInPlaylist(oldPosition, newPosition, playlistId, songId); + CServer.MoveSongInPlaylist(newPosition, playlistId, songId); } } @@ -333,9 +333,21 @@ namespace ServerLib return CServer.GetPlaylistSongs(playlistId); } - public bool IsPlaylistEditable(int playlistId) + public void RemovePlaylist(int playlistId) { - return _CheckRight(EUserRights.EditPlaylists); + if (_CheckRight(EUserRights.DeletePlaylists)) + { + CServer.RemovePlaylist(playlistId); + } + } + + public int AddPlaylist(string playlistName) + { + if (_CheckRight(EUserRights.CreatePlaylists)) + { + return CServer.AddPlaylist(playlistName); + } + return -1; } #endregion @@ -354,6 +366,11 @@ namespace ServerLib CServer.SetUserRole(profileId, userRole); } } + + public bool HasUserRight(int right) + { + return _CheckRight((EUserRights)right); + } private static bool _CheckRight(EUserRights requestedRight) { @@ -382,5 +399,6 @@ namespace ServerLib } #endregion + } } diff --git a/ClientServerLib/ClientServerLib/DataStructs.cs b/ClientServerLib/ClientServerLib/DataStructs.cs index 298fbba1..cf52fd80 100644 --- a/ClientServerLib/ClientServerLib/DataStructs.cs +++ b/ClientServerLib/ClientServerLib/DataStructs.cs @@ -108,20 +108,7 @@ namespace ServerLib public delegate SSongInfo[] GetAllSongsDelegate(); public delegate int GetCurrentSongIdDelegate(); - - 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 oldPosition, int newPosition, int playlistId, int songId); - - public delegate bool PlaylistContainsSongDelegate(int songId, int playlistId); - - public delegate SPlaylistSongInfo[] GetPlaylistSongsDelegate(int playlistId); + [DataContract] public struct SSongInfo @@ -144,6 +131,28 @@ namespace ServerLib 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] @@ -155,7 +164,8 @@ namespace ServerLib [DataMember] public int GameMode; } - + + [DataContract] public struct SPlaylistInfo { [DataMember] diff --git a/ClientServerLib/ClientServerLib/ICWebservice.cs b/ClientServerLib/ClientServerLib/ICWebservice.cs index 3a6e3326..92e1a76a 100644 --- a/ClientServerLib/ClientServerLib/ICWebservice.cs +++ b/ClientServerLib/ClientServerLib/ICWebservice.cs @@ -150,8 +150,8 @@ namespace ServerLib [OperationContract] [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, - UriTemplate = "/moveSongInPlaylist?oldPosition={oldPosition}&newPosition={newPosition}&playlistId={playlistId}&songId={songId}")] - void MoveSongInPlaylist(int oldPosition, int newPosition, int playlistId, int songId); + UriTemplate = "/moveSongInPlaylist?newPosition={newPosition}&playlistId={playlistId}&songId={songId}")] + void MoveSongInPlaylist(int newPosition, int playlistId, int songId); [OperationContract] [WebInvoke(Method = "GET", @@ -166,9 +166,14 @@ namespace ServerLib SPlaylistSongInfo[] GetPlaylistSongs(int playlistId); [OperationContract, WebInvoke(Method = "GET", - ResponseFormat = WebMessageFormat.Json, - UriTemplate = "/isPlaylistEditable?playlistId={playlistId}")] - bool IsPlaylistEditable(int playlistId); + 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 @@ -186,6 +191,12 @@ namespace ServerLib 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 } } \ No newline at end of file diff --git a/ClientServerLib/ClientServerLib/UserRights.cs b/ClientServerLib/ClientServerLib/UserRights.cs index 14c874f0..246ca978 100644 --- a/ClientServerLib/ClientServerLib/UserRights.cs +++ b/ClientServerLib/ClientServerLib/UserRights.cs @@ -10,7 +10,10 @@ namespace ServerLib UploadPhotos = 0x02, ViewOtherProfiles = 0x04, UseKeyboard = 0x08, - EditPlaylists = 0x16, - AddSongToPlaylist = 0x32 + ReorderPlaylists = 0x16, + AddSongToPlaylist = 0x32, + CreatePlaylists = 0x64, + DeletePlaylists = 0x128, + RemoveSongsFromPlaylists = 0x256 } } diff --git a/ClientServerLib/ClientServerLib/UserRoleControl.cs b/ClientServerLib/ClientServerLib/UserRoleControl.cs index 3c5eaa0e..5af1a6ba 100644 --- a/ClientServerLib/ClientServerLib/UserRoleControl.cs +++ b/ClientServerLib/ClientServerLib/UserRoleControl.cs @@ -9,8 +9,13 @@ namespace ServerLib {EUserRoles.Administrator, (EUserRights.EditAllProfiles| EUserRights.UploadPhotos| - EUserRights.ViewOtherProfiles)| - EUserRights.UseKeyboard}, + EUserRights.ViewOtherProfiles| + EUserRights.UseKeyboard| + EUserRights.AddSongToPlaylist| + EUserRights.ReorderPlaylists| + EUserRights.CreatePlaylists| + EUserRights.DeletePlaylists| + EUserRights.RemoveSongsFromPlaylists)}, {EUserRoles.AuthenticatedUser, (EUserRights.UploadPhotos| EUserRights.ViewOtherProfiles| diff --git a/Vocaluxe.sln b/Vocaluxe.sln index 16d994af..ccccbf04 100644 --- a/Vocaluxe.sln +++ b/Vocaluxe.sln @@ -189,24 +189,28 @@ Global {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|Mixed Platforms.ActiveCfg = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|Mixed Platforms.Build.0 = Debug|Any CPU {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|Any CPU.ActiveCfg = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|Any CPU.Build.0 = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|Mixed Platforms.ActiveCfg = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|Mixed Platforms.Build.0 = 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}.ReleaseLinux|Any CPU.ActiveCfg = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|Any CPU.Build.0 = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|Mixed Platforms.ActiveCfg = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|Mixed Platforms.Build.0 = 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|Any CPU.ActiveCfg = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|Any CPU.Build.0 = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|Mixed Platforms.ActiveCfg = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|Mixed Platforms.Build.0 = 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|Any CPU.ActiveCfg = Debug|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugLinux|Any CPU.Build.0 = Debug|Any CPU @@ -218,6 +222,7 @@ Global {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugWin|Mixed Platforms.ActiveCfg = Debug|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugWin|Mixed Platforms.Build.0 = 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}.ReleaseLinux|Any CPU.ActiveCfg = Release|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseLinux|Any CPU.Build.0 = Release|Any CPU @@ -229,6 +234,7 @@ Global {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|Mixed Platforms.ActiveCfg = Release|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|Mixed Platforms.Build.0 = 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 diff --git a/Vocaluxe/Base/CConfig.cs b/Vocaluxe/Base/CConfig.cs index 9902d6b9..b350c067 100644 --- a/Vocaluxe/Base/CConfig.cs +++ b/Vocaluxe/Base/CConfig.cs @@ -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 _Params = new List(); @@ -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 diff --git a/Vocaluxe/Base/CPlaylists.cs b/Vocaluxe/Base/CPlaylists.cs index 2c9e2d6a..9f0793c1 100644 --- a/Vocaluxe/Base/CPlaylists.cs +++ b/Vocaluxe/Base/CPlaylists.cs @@ -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 . +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . #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; } diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index cfaf864e..879fcb4d 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -47,7 +47,6 @@ namespace Vocaluxe.Base.Server _Clients = new Dictionary(); _Server = new CServer(CConfig.ServerPort, CConfig.ServerEncryption == EOffOn.TR_CONFIG_ON); - //TODO: remove CConfig.ServerPassword CServer.SendKeyEvent = _SendKeyEvent; CServer.GetProfileData = _GetProfileData; @@ -64,6 +63,15 @@ namespace Vocaluxe.Base.Server 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(); @@ -432,31 +440,32 @@ namespace Vocaluxe.Base.Server #region playlist - public static SPlaylistInfo[] GetPlaylists() + private static SPlaylistInfo[] _GetPlaylists() { return (from p in CPlaylists.Playlists select _GetPlaylistInfo(p)).ToArray(); } - public static SPlaylistInfo GetPlaylist(int playlistId) + private static SPlaylistInfo _GetPlaylist(int playlistId) { - if (CPlaylists.Playlists.Length <= playlistId) + if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0) { throw new ArgumentException("invalid playlistId"); } return _GetPlaylistInfo(CPlaylists.Playlists[playlistId]); } - public static void AddSongToPlaylist(int songId, int playlistId, bool allowDuplicates) + private static void _AddSongToPlaylist(int songId, int playlistId, bool allowDuplicates) { - if (CPlaylists.Playlists.Length <= playlistId) + if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0) { throw new ArgumentException("invalid playlistId"); } - if (allowDuplicates || PlaylistContainsSong(songId, playlistId)) + if (allowDuplicates || !_PlaylistContainsSong(songId, playlistId)) { CPlaylists.AddPlaylistSong(playlistId, songId); + CPlaylists.SavePlaylist(playlistId); } else { @@ -464,57 +473,58 @@ namespace Vocaluxe.Base.Server } } - public static void RemoveSongFromPlaylist(int position, int playlistId, int songId) + private static void _RemoveSongFromPlaylist(int position, int playlistId, int songId) { - if (CPlaylists.Playlists.Length <= playlistId) + if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0) { throw new ArgumentException("invalid playlistId"); } - if (!PlaylistContainsSong(songId, playlistId)) + if (!_PlaylistContainsSong(songId, playlistId)) { throw new ArgumentException("invalid songId"); } - if (CPlaylists.Playlists[playlistId].Songs.Count <= position || CPlaylists.Playlists[playlistId].Songs[position].SongID != 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); } - public static void MoveSongInPlaylist(int oldPosition, int newPosition, int playlistId, int songId) + private static void _MoveSongInPlaylist(int newPosition, int playlistId, int songId) { - if (CPlaylists.Playlists.Length <= playlistId) + if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0) { throw new ArgumentException("invalid playlistId"); } - if (!PlaylistContainsSong(songId, playlistId)) + if (!_PlaylistContainsSong(songId, playlistId)) { throw new ArgumentException("invalid songId"); } - if (CPlaylists.Playlists[playlistId].Songs.Count <= oldPosition || CPlaylists.Playlists[playlistId].Songs[oldPosition].SongID != songId) - { - throw new ArgumentException("invalid oldPosition"); - } - if (CPlaylists.Playlists[playlistId].Songs.Count < newPosition ) + + if (CPlaylists.Playlists[playlistId].Songs.Count < newPosition) { throw new ArgumentException("invalid newPosition"); } - CPlaylists.MovePlaylistSong(playlistId,oldPosition, newPosition); + int oldPosition = CPlaylists.Playlists[playlistId].Songs.FindIndex(s => s.SongID == songId); + CPlaylists.MovePlaylistSong(playlistId, oldPosition, newPosition); + CPlaylists.SavePlaylist(playlistId); } - public static bool PlaylistContainsSong(int songId, int playlistId) + private static bool _PlaylistContainsSong(int songId, int playlistId) { - if (CPlaylists.Playlists.Length <= playlistId) + if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0) { throw new ArgumentException("invalid playlistId"); } return CPlaylists.Playlists[playlistId].Songs.Any(s => s.SongID == songId); } - public static SPlaylistSongInfo[] GetPlaylistSongs(int playlistId) + private static SPlaylistSongInfo[] _GetPlaylistSongs(int playlistId) { - if (CPlaylists.Playlists.Length <= playlistId) + if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0) { throw new ArgumentException("invalid playlistId"); } @@ -540,7 +550,7 @@ namespace Vocaluxe.Base.Server SPlaylistSongInfo[] result = new SPlaylistSongInfo[playlist.Songs.Count]; for (int i = 0; i < playlist.Songs.Count; i++) { - result[i] = _GetPlaylistSongInfo(playlist.Songs[i], 1 /*TODO:PlaylistID???*/, i); + result[i] = _GetPlaylistSongInfo(playlist.Songs[i], playlist.Id, i); } return result; } @@ -549,13 +559,31 @@ namespace Vocaluxe.Base.Server { return new SPlaylistInfo { - PlaylistId = 1, /*TODO: PlaylistId*/ + 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 diff --git a/Vocaluxe/Lib/Playlist/CPlaylistFile.cs b/Vocaluxe/Lib/Playlist/CPlaylistFile.cs index d40234e9..58d2f575 100644 --- a/Vocaluxe/Lib/Playlist/CPlaylistFile.cs +++ b/Vocaluxe/Lib/Playlist/CPlaylistFile.cs @@ -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 . +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . #endregion using System; @@ -31,6 +31,7 @@ namespace Vocaluxe.Lib.Playlist { public string PlaylistName; public string PlaylistFile; + public int Id = -1; public List Songs = new List(); 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); } } diff --git a/Vocaluxe/Vocaluxe.csproj b/Vocaluxe/Vocaluxe.csproj index 622735f7..5505580c 100644 --- a/Vocaluxe/Vocaluxe.csproj +++ b/Vocaluxe/Vocaluxe.csproj @@ -343,6 +343,9 @@ css PreserveNewest + + PreserveNewest + PreserveNewest @@ -355,6 +358,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -391,10 +397,16 @@ PreserveNewest js + + PreserveNewest + js PreserveNewest + + PreserveNewest + js PreserveNewest diff --git a/Vocaluxe/Website/css/style.css b/Vocaluxe/Website/css/style.css index f568b912..e3210c83 100644 --- a/Vocaluxe/Website/css/style.css +++ b/Vocaluxe/Website/css/style.css @@ -50,10 +50,10 @@ text-align: center; } -#displaySongContent span { - font-size: 18px; - font-weight: bold; -} + #displaySongContent span { + font-size: 18px; + font-weight: bold; + } .imageLoaderImg { height: 100%; @@ -80,3 +80,8 @@ -webkit-border-radius: 0px !important; border-radius: 0px !important; } + +.cursorStyleClickable { + cursor: pointer; +} + diff --git a/Vocaluxe/Website/img/addPlaylist.png b/Vocaluxe/Website/img/addPlaylist.png new file mode 100644 index 0000000000000000000000000000000000000000..acdfe91c2409ce3a9b8709f0fc62bdcf5fcdacfd GIT binary patch literal 3760 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 z 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 M(>BohplKKKe}Wfo>i_@% literal 0 HcmV?d00001 diff --git a/Vocaluxe/Website/index.html b/Vocaluxe/Website/index.html index 06aed5fd..6858595d 100644 --- a/Vocaluxe/Website/index.html +++ b/Vocaluxe/Website/index.html @@ -7,6 +7,8 @@ + + @@ -58,11 +60,18 @@

    All songs

    -

    List all available songs

    +

    Lists all available songs

  • - + + +

    All playlists

    +

    Lists all playlists

    +
    +
  • +
  • +

    Profiles

    Shows all profiles

    @@ -76,7 +85,7 @@
  • - +

    Keyboard

    Send keys

    @@ -176,15 +185,18 @@

    @@ -284,6 +296,34 @@ +
    +
    +

    Select a playlist

    + Add +
    + + +
    +
      +
      + +
      + + +
      +
      +

      Playlist

      + Save +
      + + +
      +
        +
        + +
        + +
        diff --git a/Vocaluxe/Website/js/jquery-ui-1.10.3.custom.min.js b/Vocaluxe/Website/js/jquery-ui-1.10.3.custom.min.js new file mode 100644 index 00000000..1e73c62c --- /dev/null +++ b/Vocaluxe/Website/js/jquery-ui-1.10.3.custom.min.js @@ -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("").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("").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._super=e,this._superApply=t,i=a.apply(this,arguments),this._super=s,this._superApply=n,i}}(),t):(l[i]=a,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:n}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var a,n,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(a in r[o])n=r[o][a],r[o].hasOwnProperty(a)&&n!==t&&(i[a]=e.isPlainObject(n)?e.isPlainObject(i[a])?e.widget.extend({},i[a],n):e.widget.extend({},n):n);return i},e.widget.bridge=function(i,a){var n=a.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,a=e.data(this,n);return a?e.isFunction(a[r])&&"_"!==r.charAt(0)?(s=a[r].apply(a,h),s!==a&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,n);t?t.option(r||{})._init():e.data(this,n,new a(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
        ",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var a,n,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},a=i.split("."),i=a.shift(),a.length){for(n=o[i]=e.widget.extend({},this.options[i]),r=0;a.length-1>r;r++)n[a[r]]=n[a[r]]||{},n=n[a[r]];if(i=a.pop(),s===t)return n[i]===t?null:n[i];n[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,a){var n,r=this;"boolean"!=typeof i&&(a=s,s=i,i=!1),a?(s=n=e(s),this.bindings=this.bindings.add(s)):(a=s,s=this.element,n=this.widget()),e.each(a,function(a,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=a.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?n.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var a,n,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],n=i.originalEvent)for(a in n)a in i||(i[a]=n[a]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,a,n){"string"==typeof a&&(a={effect:a});var r,o=a?a===!0||"number"==typeof a?i:a.effect||i:t;a=a||{},"number"==typeof a&&(a={duration:a}),r=!e.isEmptyObject(a),a.complete=n,a.delay&&s.delay(a.delay),r&&e.effects&&e.effects.effect[o]?s[t](a):o!==t&&s[o]?s[o](a.duration,a.easing,n):s.queue(function(i){e(this)[t](),n&&n.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.3",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,a=1===i.which,n="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return a&&!n&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e){function t(e,t,i){return e>t&&t+i>e}function i(e){return/left|right/.test(e.css("float"))||/inline|table-cell/.test(e.css("display"))}e.widget("ui.sortable",e.ui.mouse,{version:"1.10.3",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?"x"===e.axis||i(this.items[0].item):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_setOption:function(t,i){"disabled"===t?(this.options[t]=i,this.widget().toggleClass("ui-sortable-disabled",!!i)):e.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(t,i){var s=null,a=!1,n=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(t),e(t.target).parents().each(function(){return e.data(this,n.widgetName+"-item")===n?(s=e(this),!1):undefined}),e.data(t.target,n.widgetName+"-item")===n&&(s=e(t.target)),s?!this.options.handle||i||(e(this.options.handle,s).find("*").addBack().each(function(){this===t.target&&(a=!0)}),a)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(t,i,s){var a,n,r=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,r.cursorAt&&this._adjustOffsetFromHelper(r.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),r.containment&&this._setContainment(),r.cursor&&"auto"!==r.cursor&&(n=this.document.find("body"),this.storedCursor=n.css("cursor"),n.css("cursor",r.cursor),this.storedStylesheet=e("").appendTo(n)),r.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",r.opacity)),r.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",r.zIndex)),this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(a=this.containers.length-1;a>=0;a--)this.containers[a]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!r.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){var i,s,a,n,r=this.options,o=!1;for(this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY=0;i--)if(s=this.items[i],a=s.item[0],n=this._intersectsWithPointer(s),n&&s.instance===this.currentContainer&&a!==this.currentItem[0]&&this.placeholder[1===n?"next":"prev"]()[0]!==a&&!e.contains(this.placeholder[0],a)&&("semi-dynamic"===this.options.type?!e.contains(this.element[0],a):!0)){if(this.direction=1===n?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(t,s),this._trigger("change",t,this._uiHash());break}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,i){if(t){if(e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t),this.options.revert){var s=this,a=this.placeholder.offset(),n=this.options.axis,r={};n&&"x"!==n||(r.left=a.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft)),n&&"y"!==n||(r.top=a.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,e(this.helper).animate(r,parseInt(this.options.revert,10)||500,function(){s._clear(t)})}else this._clear(t,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var i=this._getItemsAsjQuery(t&&t.connected),s=[];return t=t||{},e(i).each(function(){var i=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[\-=_](.+)/);i&&s.push((t.key||i[1]+"[]")+"="+(t.key&&t.expression?i[1]:i[2]))}),!s.length&&t.key&&s.push(t.key+"="),s.join("&")},toArray:function(t){var i=this._getItemsAsjQuery(t&&t.connected),s=[];return t=t||{},i.each(function(){s.push(e(t.item||this).attr(t.attribute||"id")||"")}),s},_intersectsWith:function(e){var t=this.positionAbs.left,i=t+this.helperProportions.width,s=this.positionAbs.top,a=s+this.helperProportions.height,n=e.left,r=n+e.width,o=e.top,h=o+e.height,l=this.offset.click.top,u=this.offset.click.left,c="x"===this.options.axis||s+l>o&&h>s+l,d="y"===this.options.axis||t+u>n&&r>t+u,p=c&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>e[this.floating?"width":"height"]?p:t+this.helperProportions.width/2>n&&r>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>o&&h>a-this.helperProportions.height/2},_intersectsWithPointer:function(e){var i="x"===this.options.axis||t(this.positionAbs.top+this.offset.click.top,e.top,e.height),s="y"===this.options.axis||t(this.positionAbs.left+this.offset.click.left,e.left,e.width),a=i&&s,n=this._getDragVerticalDirection(),r=this._getDragHorizontalDirection();return a?this.floating?r&&"right"===r||"down"===n?2:1:n&&("down"===n?2:1):!1},_intersectsWithSides:function(e){var i=t(this.positionAbs.top+this.offset.click.top,e.top+e.height/2,e.height),s=t(this.positionAbs.left+this.offset.click.left,e.left+e.width/2,e.width),a=this._getDragVerticalDirection(),n=this._getDragHorizontalDirection();return this.floating&&n?"right"===n&&s||"left"===n&&!s:a&&("down"===a&&i||"up"===a&&!i)},_getDragVerticalDirection:function(){var e=this.positionAbs.top-this.lastPositionAbs.top;return 0!==e&&(e>0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return 0!==e&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor===String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){var i,s,a,n,r=[],o=[],h=this._connectWith();if(h&&t)for(i=h.length-1;i>=0;i--)for(a=e(h[i]),s=a.length-1;s>=0;s--)n=e.data(a[s],this.widgetFullName),n&&n!==this&&!n.options.disabled&&o.push([e.isFunction(n.options.items)?n.options.items.call(n.element):e(n.options.items,n.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),n]);for(o.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),i=o.length-1;i>=0;i--)o[i][0].each(function(){r.push(this)});return e(r)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var i=0;t.length>i;i++)if(t[i]===e.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var i,s,a,n,r,o,h,l,u=this.items,c=[[e.isFunction(this.options.items)?this.options.items.call(this.element[0],t,{item:this.currentItem}):e(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(a=e(d[i]),s=a.length-1;s>=0;s--)n=e.data(a[s],this.widgetFullName),n&&n!==this&&!n.options.disabled&&(c.push([e.isFunction(n.options.items)?n.options.items.call(n.element[0],t,{item:this.currentItem}):e(n.options.items,n.element),n]),this.containers.push(n));for(i=c.length-1;i>=0;i--)for(r=c[i][1],o=c[i][0],s=0,l=o.length;l>s;s++)h=e(o[s]),h.data(this.widgetName+"-item",r),u.push({item:h,instance:r,width:0,height:0,left:0,top:0})},refreshPositions:function(t){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,a,n;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(a=this.options.toleranceElement?e(this.options.toleranceElement,s.item):s.item,t||(s.width=a.outerWidth(),s.height=a.outerHeight()),n=a.offset(),s.left=n.left,s.top=n.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)n=this.containers[i].element.offset(),this.containers[i].containerCache.left=n.left,this.containers[i].containerCache.top=n.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(t){t=t||this;var i,s=t.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=t.currentItem[0].nodeName.toLowerCase(),a=e("<"+s+">",t.document[0]).addClass(i||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");return"tr"===s?t.currentItem.children().each(function(){e("
      1. ",t.document[0]).attr("colspan",e(this).attr("colspan")||1).appendTo(a)}):"img"===s&&a.attr("src",t.currentItem.attr("src")),i||a.css("visibility","hidden"),a},update:function(e,a){(!i||s.forcePlaceholderSize)&&(a.height()||a.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),a.width()||a.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10)))}}),t.placeholder=e(s.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),s.placeholder.update(t,t.placeholder)},_contactContainers:function(s){var a,n,r,o,h,l,u,c,d,p,f=null,m=null;for(a=this.containers.length-1;a>=0;a--)if(!e.contains(this.currentItem[0],this.containers[a].element[0]))if(this._intersectsWith(this.containers[a].containerCache)){if(f&&e.contains(this.containers[a].element[0],f.element[0]))continue;f=this.containers[a],m=a}else this.containers[a].containerCache.over&&(this.containers[a]._trigger("out",s,this._uiHash(this)),this.containers[a].containerCache.over=0);if(f)if(1===this.containers.length)this.containers[m].containerCache.over||(this.containers[m]._trigger("over",s,this._uiHash(this)),this.containers[m].containerCache.over=1);else{for(r=1e4,o=null,p=f.floating||i(this.currentItem),h=p?"left":"top",l=p?"width":"height",u=this.positionAbs[h]+this.offset.click[h],n=this.items.length-1;n>=0;n--)e.contains(this.containers[m].element[0],this.items[n].item[0])&&this.items[n].item[0]!==this.currentItem[0]&&(!p||t(this.positionAbs.top+this.offset.click.top,this.items[n].top,this.items[n].height))&&(c=this.items[n].item.offset()[h],d=!1,Math.abs(c-u)>Math.abs(c+this.items[n][l]-u)&&(d=!0,c+=this.items[n][l]),r>Math.abs(c-u)&&(r=Math.abs(c-u),o=this.items[n],this.direction=d?"up":"down"));if(!o&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[m])return;o?this._rearrange(s,o,null,!0):this._rearrange(s,null,this.containers[m].element,!0),this._trigger("change",s,this._uiHash()),this.containers[m]._trigger("change",s,this._uiHash(this)),this.currentContainer=this.containers[m],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[m]._trigger("over",s,this._uiHash(this)),this.containers[m].containerCache.over=1}},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper)?e(i.helper.apply(this.element[0],[t,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||e("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&e.ui.ie)&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,a=this.options;"parent"===a.containment&&(a.containment=this.helper[0].parentNode),("document"===a.containment||"window"===a.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,e("document"===a.containment?document:window).width()-this.helperProportions.width-this.margins.left,(e("document"===a.containment?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(a.containment)||(t=e(a.containment)[0],i=e(a.containment).offset(),s="hidden"!==e(t).css("overflow"),this.containment=[i.left+(parseInt(e(t).css("borderLeftWidth"),10)||0)+(parseInt(e(t).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(e(t).css("borderTopWidth"),10)||0)+(parseInt(e(t).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(t.scrollWidth,t.offsetWidth):t.offsetWidth)-(parseInt(e(t).css("borderLeftWidth"),10)||0)-(parseInt(e(t).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(t.scrollHeight,t.offsetHeight):t.offsetHeight)-(parseInt(e(t).css("borderTopWidth"),10)||0)-(parseInt(e(t).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(t,i){i||(i=this.position);var s="absolute"===t?1:-1,a="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,n=/(html|body)/i.test(a[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():n?0:a.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():n?0:a.scrollLeft())*s}},_generatePosition:function(t){var i,s,a=this.options,n=t.pageX,r=t.pageY,o="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(o[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==document&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(t.pageX-this.offset.click.leftthis.containment[2]&&(n=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(r=this.containment[3]+this.offset.click.top)),a.grid&&(i=this.originalPageY+Math.round((r-this.originalPageY)/a.grid[1])*a.grid[1],r=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-a.grid[1]:i+a.grid[1]:i,s=this.originalPageX+Math.round((n-this.originalPageX)/a.grid[0])*a.grid[0],n=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-a.grid[0]:s+a.grid[0]:s)),{top:r-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:o.scrollTop()),left:n-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:o.scrollLeft())}},_rearrange:function(e,t,i,s){i?i[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var a=this.counter;this._delay(function(){a===this.counter&&this.refreshPositions(!s)})},_clear:function(e,t){this.reverting=!1;var i,s=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(i in this._storedCSS)("auto"===this._storedCSS[i]||"static"===this._storedCSS[i])&&(this._storedCSS[i]="");this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!t&&s.push(function(e){this._trigger("receive",e,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||t||s.push(function(e){this._trigger("update",e,this._uiHash())}),this!==this.currentContainer&&(t||(s.push(function(e){this._trigger("remove",e,this._uiHash())}),s.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),s.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer)))),i=this.containers.length-1;i>=0;i--)t||s.push(function(e){return function(t){e._trigger("deactivate",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over&&(s.push(function(e){return function(t){e._trigger("out",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,this.cancelHelperRemoval){if(!t){for(this._trigger("beforeStop",e,this._uiHash()),i=0;s.length>i;i++)s[i].call(this,e);this._trigger("stop",e,this._uiHash())}return this.fromOutside=!1,!1}if(t||this._trigger("beforeStop",e,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null,!t){for(i=0;s.length>i;i++)s[i].call(this,e);this._trigger("stop",e,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){e.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(t){var i=t||this;return{helper:i.helper,placeholder:i.placeholder||e([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:t?t.element:null}}})})(jQuery); \ No newline at end of file diff --git a/Vocaluxe/Website/js/jquery.ui.touch-punch.min.js b/Vocaluxe/Website/js/jquery.ui.touch-punch.min.js new file mode 100644 index 00000000..33d6f97e --- /dev/null +++ b/Vocaluxe/Website/js/jquery.ui.touch-punch.min.js @@ -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); \ No newline at end of file diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index 924b8b85..3e2b385e 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -2,6 +2,9 @@ var ownProfileId = -1; var profileIdRequest = -1; var songIdRequest = -1; var allSongsCache = null; +var playlistIdRequest = -1; +var playlistRequestName = ""; +var customSelectPlaylistSongCallback = null; var sessionId = ""; $(document).ready(function () { @@ -197,6 +200,8 @@ function initPageLoadHandler() { url: "getSong?songId=" + songIdRequest, headers: { "session": sessionId } }).done(function (result) { + $('#displaySongAddPlaylist').hide(); + if (result.Title != null) { $('#displaySongTitle').text(result.Title); } @@ -239,6 +244,14 @@ function initPageLoadHandler() { if (result.Title != null || result.Artist != null) { $('#displaySongLinks').show(); + $('#displaySongAddPlaylist').unbind('click').click(function () { + customSelectPlaylistSongCallback = function (playlistId) { + request({ url: "addSongToPlaylist?songId=" + result.SongId + "&playlistId=" + playlistId + "&duplicates=false" }, "Add to playlist..."); + history.back(); + }; + $.mobile.changePage("#selectPlaylist", { transition: "slidefade" }); + }); + $('#displaySongLinkYoutube').unbind('click').click(function () { showYoutube(result.Artist, result.Title); }); @@ -253,6 +266,16 @@ function initPageLoadHandler() { } else { $('#displaySongLinks').hide(); } + + request({ + url: "hasUserRight?right=" + 0x32 + }).done(function (result2) { + if (result2) { + $('#displaySongAddPlaylist').show(); + } else { + $('#displaySongAddPlaylist').hide(); + } + }); }); // Save promise on page so the transition handler can find it. @@ -280,8 +303,7 @@ function initPageLoadHandler() { if (allSongsCache == null) { var promise = request({ - url: "getAllSongs", - headers: { "session": sessionId } + url: "getAllSongs" }).done(function (data) { allSongsCache = data; handleGetAllSongs(); @@ -350,6 +372,272 @@ function initPageLoadHandler() { //pageLoadHandler for login $(document).on('pagebeforeshow', '#login', pagebeforeshowLogin); + //pageLoadHandler for main + $(document).on('pagebeforeshow', '#main', function () { + request({ + url: "hasUserRight?right=" + 0x02 + }).done(function (result) { + if (result) { + $('#mainPageTakePhotoLink').parent().parent().parent().show(); + } else { + $('#mainPageTakePhotoLink').parent().parent().parent().hide(); + } + }); + + request({ + url: "hasUserRight?right=" + 0x08 + }).done(function (result) { + if (result) { + $('#mainPageKeyboard').parent().parent().parent().show(); + } else { + $('#mainPageKeyboard').parent().parent().parent().hide(); + } + }); + + request({ + url: "hasUserRight?right=" + 0x04 + }).done(function (result) { + if (result) { + $('#mainPageSelectProfile').parent().parent().parent().show(); + } else { + $('#mainPageSelectProfile').parent().parent().parent().hide(); + } + }); + }); + + //pageLoadHandler for selectPlaylist + $(document).on('pagebeforeshow', '#selectPlaylist', function () { + function handleGetAllPlaylists(data) { + $('#selectPlaylistContentList').children().remove(); + $('#selectPlaylistAddPlaylistButton').hide(); + + function handleSelectSongLineClick(e) { + playlistIdRequest = parseInt(e.currentTarget.parentElement.parentElement.parentElement.id.replace("selectPlaylistLine_", "")); + playlistRequestName = $(e.currentTarget.parentElement.parentElement.parentElement).find('h2').text(); + if (customSelectPlaylistSongCallback != null) { + customSelectPlaylistSongCallback(playlistIdRequest, playlistRequestName); + customSelectPlaylistSongCallback = null; + } else { + + $.mobile.changePage("#displayPlaylist", { transition: "slidefade" }); + } + } + + function handleSelectSongLineDeleteClick(e) { + var playlistToDeleteId = parseInt(e.currentTarget.parentElement.id.replace("selectPlaylistLine_", "")); + var playlistToDeleteName = $(e.currentTarget.parentElement).find('h2').text(); + if (window.confirm("Do you really want to delete this playlist:\n" + playlistToDeleteName)) { + request({ url: "removePlaylist?playlistId=" + playlistToDeleteId }, "Loading...").done(function () { + request({ + url: "getPlaylists" + }).done(function (data2) { + handleGetAllPlaylists(data2); + }); + }); + } + } + + for (var id in data) { + var line = $('
      2. '/*+' '*/ + + '

        ' + data[id].PlaylistName + '

        ' + + data[id].SongCount + + ' songs

        Delete
      3. ') + .appendTo('#selectPlaylistContentList'); + line.find('a:not(.delete)').click(handleSelectSongLineClick); + line.find('a.delete').click(handleSelectSongLineDeleteClick); + } + + $('#selectPlaylistContentList').listview('refresh'); + + request({ + url: "hasUserRight?right=" + 0x128 + }).done(function (result) { + if (result) { + $('#selectPlaylistContentList').find('.delete').show(); + $('#selectPlaylistContentList').listview('refresh'); + } else { + $('#selectPlaylistContentList').find('.delete').hide(); + $('#selectPlaylistContentList').listview('refresh'); + } + }); + + $('#selectPlaylistAddPlaylistButton').unbind('click').hide().click(function () { + var name = prompt("Name of the new playlist:", "NewPlaylistName"); + if (name != null + && name.replace(" ", "") != "" + && $('h2').filter(function () { return this.textContent == name; }).length == 0) { + request({ url: "addPlaylist?playlistName=" + name }, "Creating...").done(function () { + request({ + url: "getPlaylists" + }).done(function (data2) { + handleGetAllPlaylists(data2); + }); + }); + } else { + alert("This is not a name."); + } + }); + + request({ + url: "hasUserRight?right=" + 0x64 + }).done(function (result) { + if (result) { + $('#selectPlaylistAddPlaylistButton').show(); + } else { + $('#selectPlaylistAddPlaylistButton').hide(); + } + }); + } + + var promise = request({ + url: "getPlaylists" + }).done(function (data) { + handleGetAllPlaylists(data); + }); + + // Save promise on page so the transition handler can find it. + $(this).data('promise', promise); + + }); + + //pageLoadHandler for displayPlaylist + $(document).on('pagebeforeshow', '#displayPlaylist', function () { + function handleGetAllPlaylistSongs(data) { + $('#displayPlaylistHeader').find('h1').text(playlistRequestName); + + $('#displayPlaylistSaveButton').hide().unbind('click').click(function () { + var promises = []; + $('#displayPlaylistContentList').find('li').each(function (indx, elem) { + var newPos = $(elem).index(); + var oldPos = $(elem).data("oldPos"); + if (newPos != oldPos) { + var movedId = elem.id.replace("selectSongLine_", ""); + + promises.push(request({ + url: "moveSongInPlaylist?&newPosition=" + newPos + "&playlistId=" + playlistIdRequest + "&songId=" + movedId + }, "Resorting...")); + } + }); + + $.when.apply(promises).done(function () { + //reload data + request({ + url: "getPlaylistSongs?playlistId=" + playlistIdRequest + }).done(function (data2) { + handleGetAllPlaylistSongs(data2); + }); + }); + }); + + $('#displayPlaylistContentList').children().remove(); + + function handleSelectPlaylistSongLineClick(e) { + songIdRequest = parseInt(e.currentTarget.parentElement.parentElement.parentElement.id.replace("selectSongLine_", "")); + $.mobile.changePage("#displaySong", { transition: "slidefade" }); + } + + function handleSelectPlaylistSongLineDeleteClick(e) { + var songToDeleteId = parseInt(e.currentTarget.parentElement.id.replace("selectSongLine_", "")); + var songToDeleteName = $(e.currentTarget.parentElement).find('h2').text(); + + if (window.confirm("Do you really want to delete this song from playlist:\n" + songToDeleteName)) { + request({ + url: "/removeSongFromPlaylist?position=" + $('#selectSongLine_' + songToDeleteId).index() + + "&playlistId=" + playlistIdRequest + + "&songId=" + songToDeleteId + }, "Loading...").done(function () { + //reload data + request({ + url: "getPlaylistSongs?playlistId=" + playlistIdRequest + }).done(function (data2) { + handleGetAllPlaylistSongs(data2); + }); + }); + } + + + } + + var sortedData = []; + + for (var id1 in data) { + sortedData[data[id1].PlaylistPosition] = data[id1].Song; + } + var i = 0; + for (var id in sortedData) { + var line = $('
      4. ' + + sortedData[id].Artist + + '

        ' + + sortedData[id].Title + + '

        Delete
      5. ') + .appendTo('#displayPlaylistContentList').data("oldPos", i++); + + line.find('a:not(.delete)').click(handleSelectPlaylistSongLineClick); + line.find('a.delete').click(handleSelectPlaylistSongLineDeleteClick); + + var img = line.find("img")[0]; + + addImage(img, sortedData[id].Cover, "img/noCover.png"); + } + + $('#displayPlaylistContentList').listview('refresh'); + + request({ + url: "hasUserRight?right=" + 0x256 + }).done(function (result) { + if (result) { + $('#displayPlaylistContentList').find('.delete').show(); + $('#displayPlaylistContentList').listview('refresh'); + } else { + $('#displayPlaylistContentList').find('.delete').hide(); + $('#displayPlaylistContentList').listview('refresh'); + } + }); + + request({ + url: "hasUserRight?right=" + 0x16 + }).done(function (result) { + if (result) { + $('#displayPlaylistContentList').sortable({ + axis: 'y', + sort: function () { + $('#displayPlaylistSaveButton').show(); + + var $lis = $(this).children('li'); + $lis.each(function () { + var $li = $(this); + var hindex = $lis.filter('.ui-sortable-helper').index(); + if (!$li.is('.ui-sortable-helper')) { + var index = $li.index(); + index = index < hindex ? index + 1 : index; + + $li.val(index); + + if ($li.is('.ui-sortable-placeholder')) { + $lis.filter('.ui-sortable-helper').val(index); + } + } + }); + } + }); + } + }); + } + + var promise = request({ + url: "getPlaylistSongs?playlistId=" + playlistIdRequest + }).done(function (data) { + handleGetAllPlaylistSongs(data); + }); + + // Save promise on page so the transition handler can find it. + $(this).data('promise', promise); + + }); } function pagebeforeshowLogin() { From 4c932ba85caab25e242db9590c913095f239c3d2 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 10 Nov 2013 12:41:24 +0100 Subject: [PATCH 43/81] Exclude output --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f89e714b..1686a7fa 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,4 @@ AndroidRemote.dll.mdb /Output/ClientServerLib.dll Installer/VocaluxeSetup_0.3.0Beta.exe Output/Vocaluxe_x64.exe +/WebserverInitalConfig/bin/Release From e68dafd16e9e50288836d7414bef1a5ed0b562a9 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 10 Nov 2013 14:20:30 +0100 Subject: [PATCH 44/81] Webserver: Fixed a userrights bug --- .../ClientServerLib/SessionControl.cs | 4 ++-- ClientServerLib/ClientServerLib/UserRights.cs | 20 +++++++++---------- ClientServerLib/ClientServerLib/UserRoles.cs | 4 ++-- Vocaluxe/Website/js/main.js | 16 +++++++-------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/ClientServerLib/ClientServerLib/SessionControl.cs b/ClientServerLib/ClientServerLib/SessionControl.cs index cf92484d..eee8fc2a 100644 --- a/ClientServerLib/ClientServerLib/SessionControl.cs +++ b/ClientServerLib/ClientServerLib/SessionControl.cs @@ -48,12 +48,12 @@ namespace ServerLib { _ActiveSessions.Remove(s.Key); } - } internal static bool RequestRight(Guid sessionId, EUserRights requestedRight) { - return ((CUserRoleControl.GetUserRightsFromUserRole(_ActiveSessions[sessionId].Roles) & requestedRight) != 0); + return ((CUserRoleControl.GetUserRightsFromUserRole(_ActiveSessions[sessionId].Roles) + .HasFlag(requestedRight))); } internal static int GetUserIdFromSession(Guid sessionId) diff --git a/ClientServerLib/ClientServerLib/UserRights.cs b/ClientServerLib/ClientServerLib/UserRights.cs index 246ca978..d5d71fbe 100644 --- a/ClientServerLib/ClientServerLib/UserRights.cs +++ b/ClientServerLib/ClientServerLib/UserRights.cs @@ -5,15 +5,15 @@ namespace ServerLib [Flags] internal enum EUserRights { - None = 0x00, - EditAllProfiles = 0x01, - UploadPhotos = 0x02, - ViewOtherProfiles = 0x04, - UseKeyboard = 0x08, - ReorderPlaylists = 0x16, - AddSongToPlaylist = 0x32, - CreatePlaylists = 0x64, - DeletePlaylists = 0x128, - RemoveSongsFromPlaylists = 0x256 + None = 0, + EditAllProfiles = 1, + UploadPhotos = 2, + ViewOtherProfiles = 4, + UseKeyboard = 8, + ReorderPlaylists = 16, + AddSongToPlaylist = 32, + CreatePlaylists = 64, + DeletePlaylists = 128, + RemoveSongsFromPlaylists = 256 } } diff --git a/ClientServerLib/ClientServerLib/UserRoles.cs b/ClientServerLib/ClientServerLib/UserRoles.cs index 0294a029..b352317c 100644 --- a/ClientServerLib/ClientServerLib/UserRoles.cs +++ b/ClientServerLib/ClientServerLib/UserRoles.cs @@ -5,7 +5,7 @@ namespace ServerLib [Flags] internal enum EUserRoles { - AuthenticatedUser = 0x00, - Administrator = 0x01 + AuthenticatedUser = 0, + Administrator = 1 } } diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index 3e2b385e..3ea9bd49 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -268,7 +268,7 @@ function initPageLoadHandler() { } request({ - url: "hasUserRight?right=" + 0x32 + url: "hasUserRight?right=" + 32 }).done(function (result2) { if (result2) { $('#displaySongAddPlaylist').show(); @@ -375,7 +375,7 @@ function initPageLoadHandler() { //pageLoadHandler for main $(document).on('pagebeforeshow', '#main', function () { request({ - url: "hasUserRight?right=" + 0x02 + url: "hasUserRight?right=" + 2 }).done(function (result) { if (result) { $('#mainPageTakePhotoLink').parent().parent().parent().show(); @@ -385,7 +385,7 @@ function initPageLoadHandler() { }); request({ - url: "hasUserRight?right=" + 0x08 + url: "hasUserRight?right=" + 8 }).done(function (result) { if (result) { $('#mainPageKeyboard').parent().parent().parent().show(); @@ -395,7 +395,7 @@ function initPageLoadHandler() { }); request({ - url: "hasUserRight?right=" + 0x04 + url: "hasUserRight?right=" + 4 }).done(function (result) { if (result) { $('#mainPageSelectProfile').parent().parent().parent().show(); @@ -452,7 +452,7 @@ function initPageLoadHandler() { $('#selectPlaylistContentList').listview('refresh'); request({ - url: "hasUserRight?right=" + 0x128 + url: "hasUserRight?right=" + 128 }).done(function (result) { if (result) { $('#selectPlaylistContentList').find('.delete').show(); @@ -481,7 +481,7 @@ function initPageLoadHandler() { }); request({ - url: "hasUserRight?right=" + 0x64 + url: "hasUserRight?right=" + 64 }).done(function (result) { if (result) { $('#selectPlaylistAddPlaylistButton').show(); @@ -587,7 +587,7 @@ function initPageLoadHandler() { $('#displayPlaylistContentList').listview('refresh'); request({ - url: "hasUserRight?right=" + 0x256 + url: "hasUserRight?right=" + 256 }).done(function (result) { if (result) { $('#displayPlaylistContentList').find('.delete').show(); @@ -599,7 +599,7 @@ function initPageLoadHandler() { }); request({ - url: "hasUserRight?right=" + 0x16 + url: "hasUserRight?right=" + 16 }).done(function (result) { if (result) { $('#displayPlaylistContentList').sortable({ From 21fb55ddeade06ec0d9339de0dfcf7fd58bc338a Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 10 Nov 2013 14:25:52 +0100 Subject: [PATCH 45/81] Webserver: fixed errormessages on sucessfull requests --- .../ClientServerLib/CWebservice.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs index 15990d3c..7570e39b 100644 --- a/ClientServerLib/ClientServerLib/CWebservice.cs +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -369,7 +369,7 @@ namespace ServerLib public bool HasUserRight(int right) { - return _CheckRight((EUserRights)right); + return _CheckRightWithNoErrorMessage((EUserRights)right); } private static bool _CheckRight(EUserRights requestedRight) @@ -398,6 +398,23 @@ namespace ServerLib 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 } From bf80f46d9b3c6cc95ff61a8e81b3befbfa91f2f5 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 10 Nov 2013 14:37:31 +0100 Subject: [PATCH 46/81] Webserver: fixed: heartbeat caused a short loading screen --- Vocaluxe/Website/js/main.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index 3ea9bd49..15ffb8ae 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -873,11 +873,11 @@ function checkSession() { } request({ url: "getOwnProfileId" - }).done(function (result) { + }, "noOverlay").done(function (result) { if (result == -1) { logout(); } - }, "noOverlay").fail(function (result) { + }).fail(function (result) { logout(); }); } @@ -887,7 +887,7 @@ function initHeartbeat() { } function request(data, message) { - if (!message) { + if ((typeof message) == "undefined" || message == null) { message = "Loading..."; } From a69dd4344dcdb93ca3352dc599887e7c81f94add Mon Sep 17 00:00:00 2001 From: lukeIam Date: Mon, 11 Nov 2013 20:44:44 +0100 Subject: [PATCH 47/81] Webserver: External dlls are now included and paths are fixed --- Output/Interop.NetFwTypeLib.dll | Bin 0 -> 19456 bytes Output/Security.Cryptography.dll | Bin 0 -> 95232 bytes Output/Security.dll | Bin 0 -> 27648 bytes .../WebserverInitalConfig.csproj | 27 +++++++----------- 4 files changed, 11 insertions(+), 16 deletions(-) create mode 100644 Output/Interop.NetFwTypeLib.dll create mode 100644 Output/Security.Cryptography.dll create mode 100644 Output/Security.dll diff --git a/Output/Interop.NetFwTypeLib.dll b/Output/Interop.NetFwTypeLib.dll new file mode 100644 index 0000000000000000000000000000000000000000..135c15c507c35a142ea55b099e43fc9daf5e0f4d GIT binary patch literal 19456 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 Vc()4~_ImzDbN&CB{hsu|{{i(%*gF6K literal 0 HcmV?d00001 diff --git a/Output/Security.Cryptography.dll b/Output/Security.Cryptography.dll new file mode 100644 index 0000000000000000000000000000000000000000..d19198541fe092e486dbcc7ee6612328ed141a70 GIT binary patch literal 95232 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

        T$6{{`%iKWQ8BX3}Cojb)FI`=EiB*+&rjx6O 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 TVYrh}_kT-)|6e)nHSqrd0xNr- literal 0 HcmV?d00001 diff --git a/Output/Security.dll b/Output/Security.dll new file mode 100644 index 0000000000000000000000000000000000000000..f0c2c5139f29056216cc34e9e796ab0aa761fd4c GIT binary patch literal 27648 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.manifest - - ..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio 11.0\Libs\clrsecurity_june10\Security.dll - False + + False + True + ..\Output\Interop.NetFwTypeLib.dll - - ..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio 11.0\Libs\clrsecurity_june10\Security.Cryptography.dll + + False + ..\Output\Security.dll + + + False + ..\Output\Security.Cryptography.dll @@ -63,17 +69,6 @@ Designer - - - {58FBCF7C-E7A9-467C-80B3-FC65E8FCCA08} - 1 - 0 - 0 - tlbimp - False - True - -

        - + - +
        - Login +


        - Create Profile +
        @@ -45,64 +46,64 @@
      6. -

        Your Profile

        -

        Edit your profile

        +

        +

      7. -

        Current Song

        -

        Display informations about the current song

        +

        +

      8. -

        All songs

        -

        Lists all available songs

        +

        +

      9. -

        All playlists

        -

        Lists all playlists

        +

        +

      10. -

        Profiles

        -

        Shows all profiles

        +

        +

      11. -

        Take Photo

        -

        Takes a photo and displays it at the end of the current round

        +

        +

      12. -

        Keyboard

        -

        Send keys

        +

        +

      13. -

        Administration

        -

        Configure user rights

        +

        +

      14. -

        Logout

        -

        Closes the session

        +

        +

      15. @@ -113,7 +114,7 @@
        -

        All profiles

        +

        @@ -126,32 +127,32 @@
        -

        Profile

        +

        Profile

        Avatar - + - + - + - +
        - Save and upload +
        @@ -159,7 +160,7 @@
        -

        No current song

        +

        @@ -168,19 +169,19 @@


        - + -
        - + -
        - + -
        - + -
        - + -

        @@ -196,7 +197,7 @@
        - Close +
        @@ -205,7 +206,7 @@
        -

        All songs

        +

        @@ -218,7 +219,7 @@
        -

        Keyboard

        +

        @@ -226,36 +227,36 @@
        - up +
        - left +
        - right +
        - down +
        - escape +
        - tab +
        - return +
        - +
        @@ -265,7 +266,7 @@
        -

        All profiles

        +

        @@ -278,7 +279,7 @@
        -

        Profile

        +

        @@ -290,7 +291,7 @@ - Save +
        @@ -298,8 +299,8 @@
        -

        Select a playlist

        - Add +

        +
        @@ -312,8 +313,8 @@
        -

        Playlist

        - Save +

        +
        diff --git a/Vocaluxe/Website/js/i18next-1.7.1.min.js b/Vocaluxe/Website/js/i18next-1.7.1.min.js new file mode 100644 index 00000000..7cf162f8 --- /dev/null +++ b/Vocaluxe/Website/js/i18next-1.7.1.min.js @@ -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;cd?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(l1&&(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)}function j(a,b){var c={dynamicLoad:G.dynamicLoad,resGetPath:G.resGetPath,getAsync:G.getAsync,customLoad:G.customLoad,ns:{namespaces:a,defaultNs:""}},d=K.toLanguages(G.lng);"string"==typeof G.preload&&(G.preload=[G.preload]);for(var e=0,f=G.preload.length;f>e;e++)for(var g=K.toLanguages(G.preload[e]),h=0,i=g.length;i>h;h++)d.indexOf(g[h])<0&&d.push(g[h]);for(var j=[],k=0,l=d.length;l>k;k++){var m=!1,n=C[d[k]];if(n)for(var o=0,p=a.length;p>o;o++)n[a[o]]||(m=!0);else m=!0;m&&j.push(d[k])}j.length?B.sync._fetch(j,c,function(c,d){var e=a.length*j.length;K.each(a,function(a,c){G.ns.namespaces.indexOf(c)<0&&G.ns.namespaces.push(c),K.each(j,function(a,f){C[f]=C[f]||{},C[f][c]=d[f][c],e--,0===e&&b&&(G.useLocalStorage&&B.sync._storeLocal(C),b())})})}):b&&b()}function k(a,b,c){return"function"==typeof b&&(c=b,b={}),b.lng=a,e(b,c)}function l(){return y}function m(){function a(a,b,c){if(0!==b.length){var d="text";if(0===b.indexOf("[")){var e=b.split("]");b=e[1],d=e[0].substr(1,e[0].length-1)}b.indexOf(";")===b.length-1&&(b=b.substr(0,b.length-2));var f;"html"===d?(f=G.defaultValueFromContent?A.extend({defaultValue:a.html()},c):c,a.html(A.t(b,f))):"text"===d?(f=G.defaultValueFromContent?A.extend({defaultValue:a.text()},c):c,a.text(A.t(b,f))):(f=G.defaultValueFromContent?A.extend({defaultValue:a.attr(d)},c):c,a.attr(d,A.t(b,f)))}}function b(b,c){var d=b.attr(G.selectorAttr);if(d||"undefined"==typeof d||d===!1||(d=b.text()||b.val()),d){var e=b,f=b.data("i18n-target");if(f&&(e=b.find(f)||b),c||G.useDataAttrOptions!==!0||(c=b.data("i18n-options")),c=c||{},d.indexOf(";")>=0){var g=d.split(";");A.each(g,function(b,d){""!==d&&a(e,d,c)})}else a(e,d,c);G.useDataAttrOptions===!0&&b.data("i18n-options",c)}}A.t=A.t||s,A.fn.i18n=function(a){return this.each(function(){b(A(this),a);var c=A(this).find("["+G.selectorAttr+"]");c.each(function(){b(A(this),a)})})}}function n(a,b,c,d){if(!a)return a;if(d=d||b,a.indexOf(d.interpolationPrefix||G.interpolationPrefix)<0)return a;var e=d.interpolationPrefix?K.regexEscape(d.interpolationPrefix):G.interpolationPrefixEscaped,f=d.interpolationSuffix?K.regexEscape(d.interpolationSuffix):G.interpolationSuffixEscaped,g="HTML"+f;return K.each(b,function(b,h){var i=c?c+G.keyseparator+b:b;"object"==typeof h&&null!==h?a=n(a,h,i,d):d.escapeInterpolation||G.escapeInterpolation?(a=a.replace(new RegExp([e,i,g].join(""),"g"),h),a=a.replace(new RegExp([e,i,f].join(""),"g"),K.escape(h))):a=a.replace(new RegExp([e,i,f].join(""),"g"),h)}),a}function o(a,b){var c=",",d="{",e="}",f=K.extend({},b);for(delete f.postProcess;-1!=a.indexOf(G.reusePrefix)&&(D++,!(D>G.maxRecursion));){var g=a.lastIndexOf(G.reusePrefix),h=a.indexOf(G.reuseSuffix,g)+G.reuseSuffix.length,i=a.substring(g,h),j=i.replace(G.reusePrefix,"").replace(G.reuseSuffix,"");if(-1!=j.indexOf(c)){var k=j.indexOf(c);if(-1!=j.indexOf(d,k)&&-1!=j.indexOf(e,k)){var l=j.indexOf(d,k),m=j.indexOf(e,l)+e.length;try{f=K.extend(f,JSON.parse(j.substring(l,m))),j=j.substring(0,k)}catch(n){}}}var o=v(j,f);a=a.replace(i,o)}return a}function p(a){return a.context&&"string"==typeof a.context}function q(a){return void 0!==a.count&&"string"!=typeof a.count&&1!==a.count}function r(a,b){b=b||{};var c=t(a,b),d=w(a,b);return void 0!==d||d===c}function s(a,b){return F?(D=0,v.apply(null,arguments)):(K.log("i18next not finished initialization. you might have called t function before loading resources finished."),b.defaultValue||"")}function t(a,b){return void 0!==b.defaultValue?b.defaultValue:a}function u(){for(var a=[],b=1;b-1&&(e=c.split(G.nsseparator),i=e[0],c=e[1]),void 0===g&&G.sendMissing&&(b.lng?L.postMissing(h[0],i,c,f,h):L.postMissing(G.lng,i,c,f,h));var j=b.postProcess||G.postProcess;void 0!==g&&j&&N[j]&&(g=N[j](g,c,b));var k=f;if(f.indexOf(G.nsseparator)>-1&&(e=f.split(G.nsseparator),k=e[1]),k===c&&G.parseMissingKey&&(f=G.parseMissingKey(f)),void 0===g&&(f=n(f,b),f=o(f,b),j&&N[j])){var l=t(c,b);g=N[j](l,c,b)}return void 0!==g?g:f}function w(a,b){b=b||{};var c,d,e=t(a,b),f=E;if(!C)return e;if(b.lng&&(f=K.toLanguages(b.lng),!C[f[0]])){var g=G.getAsync;G.getAsync=!1,B.sync.load(f,G,function(a,b){K.extend(C,b),G.getAsync=g})}var h=b.ns||G.ns.defaultNs;if(a.indexOf(G.nsseparator)>-1){var i=a.split(G.nsseparator);h=i[0],a=i[1]}if(p(b)){c=K.extend({},b),delete c.context,c.defaultValue=G.contextNotFound;var j=h+G.nsseparator+a+"_"+b.context;if(d=s(j,c),d!=G.contextNotFound)return n(d,{context:b.context})}if(q(b)){c=K.extend({},b),delete c.count,c.defaultValue=G.pluralNotFound;var k=h+G.nsseparator+a+G.pluralSuffix,l=M.get(f[0],b.count);if(l>=0?k=k+"_"+l:1===l&&(k=h+G.nsseparator+a),d=s(k,c),d!=G.pluralNotFound)return n(d,{count:b.count,interpolationPrefix:b.interpolationPrefix,interpolationSuffix:b.interpolationSuffix})}for(var m,r=a.split(G.keyseparator),u=0,x=f.length;x>u&&void 0===m;u++){for(var y=f[u],z=0,A=C[y]&&C[y][h];r[z];)A=A&&A[r[z]],z++;if(void 0!==A){if("string"==typeof A)A=n(A,b),A=o(A,b);else if("[object Array]"!==Object.prototype.toString.apply(A)||G.returnObjectTrees||b.returnObjectTrees){if(null===A&&G.fallbackOnNull===!0)A=void 0;else if(null!==A)if(G.returnObjectTrees||b.returnObjectTrees){if("number"!=typeof A){var D={};K.each(A,function(c){D[c]=v(h+G.nsseparator+a+G.keyseparator+c,b)}),A=D}}else A="key '"+h+":"+a+" ("+y+")' "+"returned a object instead of string.",K.log(A)}else A=A.join("\n"),A=n(A,b),A=o(A,b);m=A}}if(void 0===m&&!b.isFallbackLookup&&(G.fallbackToDefaultNS===!0||G.fallbackNS&&G.fallbackNS.length>0))if(b.isFallbackLookup=!0,G.fallbackNS.length){for(var F=0,H=G.fallbackNS.length;H>F;F++)if(m=w(G.fallbackNS[F]+G.nsseparator+a,b)){var I=m.indexOf(G.nsseparator)>-1?m.split(G.nsseparator)[1]:m,J=e.indexOf(G.nsseparator)>-1?e.split(G.nsseparator)[1]:e;if(I!==J)break}}else m=w(a,b);return m}function x(){var a,b=[];if("undefined"!=typeof window&&(!function(){for(var a=window.location.search.substring(1),c=a.split("&"),d=0;d0){var f=c[d].substring(0,e),g=c[d].substring(e+1);b[f]=g}}}(),b[G.detectLngQS]&&(a=b[G.detectLngQS])),!a&&"undefined"!=typeof document&&G.useCookie){var c=K.cookie.read(G.cookieName);c&&(a=c)}return a||"undefined"==typeof navigator||(a=navigator.language?navigator.language:navigator.userLanguage),a}Array.prototype.indexOf||(Array.prototype.indexOf=function(a){"use strict";if(null==this)throw new TypeError;var b=Object(this),c=b.length>>>0;if(0===c)return-1;var d=0;if(arguments.length>0&&(d=Number(arguments[1]),d!=d?d=0:0!=d&&1/0!=d&&d!=-1/0&&(d=(d>0||-1)*Math.floor(Math.abs(d)))),d>=c)return-1;for(var e=d>=0?d:Math.max(c-Math.abs(d),0);c>e;e++)if(e in b&&b[e]===a)return e;return-1}),Array.prototype.lastIndexOf||(Array.prototype.lastIndexOf=function(a){"use strict";if(null==this)throw new TypeError;var b=Object(this),c=b.length>>>0;if(0===c)return-1;var d=c;arguments.length>1&&(d=Number(arguments[1]),d!=d?d=0:0!=d&&d!=1/0&&d!=-(1/0)&&(d=(d>0||-1)*Math.floor(Math.abs(d))));for(var e=d>=0?Math.min(d,c-1):c-Math.abs(d);e>=0;e--)if(e in b&&b[e]===a)return e;return-1});var y,z=this,A=z.jQuery||z.Zepto,B={},C={},D=0,E=[],F=!1;"undefined"!=typeof module&&module.exports?module.exports=B:(A&&(A.i18n=A.i18n||B),z.i18n=z.i18n||B);var G={lng:void 0,load:"all",preload:[],lowerCaseLng:!1,returnObjectTrees:!1,fallbackLng:"dev",fallbackNS:[],detectLngQS:"setLng",ns:"translation",fallbackOnNull:!0,fallbackToDefaultNS:!1,nsseparator:":",keyseparator:".",selectorAttr:"data-i18n",debug:!1,resGetPath:"locales/__lng__/__ns__.json",resPostPath:"locales/add/__lng__/__ns__",getAsync:!0,postAsync:!0,resStore:void 0,useLocalStorage:!1,localStorageExpirationTime:6048e5,dynamicLoad:!1,sendMissing:!1,sendMissingTo:"fallback",sendType:"POST",interpolationPrefix:"__",interpolationSuffix:"__",reusePrefix:"$t(",reuseSuffix:")",pluralSuffix:"_plural",pluralNotFound:["plural_not_found",Math.random()].join(""),contextNotFound:["context_not_found",Math.random()].join(""),escapeInterpolation:!1,setJqueryExt:!0,defaultValueFromContent:!0,useDataAttrOptions:!1,cookieExpirationTime:void 0,useCookie:!0,cookieName:"i18next",cookieDomain:void 0,postProcess:void 0,parseMissingKey:void 0,shortcutFunction:"sprintf"},H={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},I={create:function(a,b,c,d){var e;if(c){var f=new Date;f.setTime(f.getTime()+1e3*60*c),e="; expires="+f.toGMTString()}else e="";d=d?"domain="+d+";":"",document.cookie=a+"="+b+e+";"+d+"path=/"},read:function(a){for(var b=a+"=",c=document.cookie.split(";"),d=0;d-1){var c=a.split("-");a=G.lowerCaseLng?c[0].toLowerCase()+"-"+c[1].toLowerCase():c[0].toLowerCase()+"-"+c[1].toUpperCase(),"unspecific"!==G.load&&b.push(a),"current"!==G.load&&b.push(c[0])}else b.push(a);return-1===b.indexOf(G.fallbackLng)&&G.fallbackLng&&b.push(G.fallbackLng),b},regexEscape:function(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}};K.applyReplacement=n;var L={load:function(a,b,c){b.useLocalStorage?L._loadLocal(a,b,function(d,e){for(var f=[],g=0,h=a.length;h>g;g++)e[a[g]]||f.push(a[g]);f.length>0?L._fetch(f,b,function(a,b){K.extend(e,b),L._storeLocal(b),c(null,e)}):c(null,e)}):L._fetch(a,b,function(a,b){c(null,b)})},_loadLocal:function(a,b,c){var d={},e=(new Date).getTime();if(window.localStorage){var f=a.length;K.each(a,function(a,g){var h=window.localStorage.getItem("res_"+g);h&&(h=JSON.parse(h),h.i18nStamp&&h.i18nStamp+b.localStorageExpirationTime>e&&(d[g]=h)),f--,0===f&&c(null,d)})}},_storeLocal:function(a){if(window.localStorage)for(var b in a)a[b].i18nStamp=(new Date).getTime(),window.localStorage.setItem("res_"+b,JSON.stringify(a[b]))},_fetch:function(a,b,c){var d=b.ns,e={};if(b.dynamicLoad){var f=function(a,b){c(null,b)};if("function"==typeof b.customLoad)b.customLoad(a,d.namespaces,b,f);else{var g=n(b.resGetPath,{lng:a.join("+"),ns:d.namespaces.join("+")});K.ajax({url:g,success:function(a){K.log("loaded: "+g),f(null,a)},error:function(a,b,c){K.log("failed loading: "+g),f("failed loading resource.json error: "+c)},dataType:"json",async:b.getAsync})}}else{var h,i=d.namespaces.length*a.length;K.each(d.namespaces,function(d,f){K.each(a,function(a,d){var g=function(a,b){a&&(h=h||[],h.push(a)),e[d]=e[d]||{},e[d][f]=b,i--,0===i&&c(h,e)};"function"==typeof b.customLoad?b.customLoad(d,f,b,g):L._fetchOne(d,f,b,g)})})}},_fetchOne:function(a,b,c,d){var e=n(c.resGetPath,{lng:a,ns:b});K.ajax({url:e,success:function(a){K.log("loaded: "+e),d(null,a)},error:function(a,b,c){K.log("failed loading: "+e),d(c,{})},dataType:"json",async:c.getAsync})},postMissing:function(a,b,c,d,e){var f={};f[c]=d;var g=[];if("fallback"===G.sendMissingTo&&G.fallbackLng!==!1)g.push({lng:G.fallbackLng,url:n(G.resPostPath,{lng:G.fallbackLng,ns:b})});else if("current"===G.sendMissingTo||"fallback"===G.sendMissingTo&&G.fallbackLng===!1)g.push({lng:a,url:n(G.resPostPath,{lng:a,ns:b})});else if("all"===G.sendMissingTo)for(var h=0,i=e.length;i>h;h++)g.push({lng:e[h],url:n(G.resPostPath,{lng:e[h],ns:b})});for(var j=0,k=g.length;k>j;j++){var l=g[j];K.ajax({url:l.url,type:G.sendType,data:f,success:function(){K.log("posted missing key '"+c+"' to: "+l.url);for(var a=c.split("."),e=0,f=C[l.lng][b];a[e];)f=f[a[e]]=e===a.length-1?d:f[a[e]]||{},e++},error:function(){K.log("failed posting missing key '"+c+"' to: "+l.url)},dataType:"json",async:G.postAsync})}}},M={rules:{ach:{name:"Acholi",numbers:[1,2],plurals:function(a){return Number(a>1)}},af:{name:"Afrikaans",numbers:[1,2],plurals:function(a){return Number(1!=a)}},ak:{name:"Akan",numbers:[1,2],plurals:function(a){return Number(a>1)}},am:{name:"Amharic",numbers:[1,2],plurals:function(a){return Number(a>1)}},an:{name:"Aragonese",numbers:[1,2],plurals:function(a){return Number(1!=a)}},ar:{name:"Arabic",numbers:[0,1,2,3,11,100],plurals:function(a){return Number(0===a?0:1==a?1:2==a?2:a%100>=3&&10>=a%100?3:a%100>=11?4:5)}},arn:{name:"Mapudungun",numbers:[1,2],plurals:function(a){return Number(a>1)}},ast:{name:"Asturian",numbers:[1,2],plurals:function(a){return Number(1!=a)}},ay:{name:"Aymará",numbers:[1],plurals:function(){return 0}},az:{name:"Azerbaijani",numbers:[1,2],plurals:function(a){return Number(1!=a)}},be:{name:"Belarusian",numbers:[1,2,5],plurals:function(a){return Number(1==a%10&&11!=a%100?0:a%10>=2&&4>=a%10&&(10>a%100||a%100>=20)?1:2)}},bg:{name:"Bulgarian",numbers:[1,2],plurals:function(a){return Number(1!=a)}},bn:{name:"Bengali",numbers:[1,2],plurals:function(a){return Number(1!=a)}},bo:{name:"Tibetan",numbers:[1],plurals:function(){return 0}},br:{name:"Breton",numbers:[1,2],plurals:function(a){return Number(a>1)}},bs:{name:"Bosnian",numbers:[1,2,5],plurals:function(a){return Number(1==a%10&&11!=a%100?0:a%10>=2&&4>=a%10&&(10>a%100||a%100>=20)?1:2)}},ca:{name:"Catalan",numbers:[1,2],plurals:function(a){return Number(1!=a)}},cgg:{name:"Chiga",numbers:[1],plurals:function(){return 0}},cs:{name:"Czech",numbers:[1,2,5],plurals:function(a){return Number(1==a?0:a>=2&&4>=a?1:2)}},csb:{name:"Kashubian",numbers:[1,2,5],plurals:function(a){return Number(1==a?0:a%10>=2&&4>=a%10&&(10>a%100||a%100>=20)?1:2)}},cy:{name:"Welsh",numbers:[1,2,3,8],plurals:function(a){return Number(1==a?0:2==a?1:8!=a&&11!=a?2:3)}},da:{name:"Danish",numbers:[1,2],plurals:function(a){return Number(1!=a)}},de:{name:"German",numbers:[1,2],plurals:function(a){return Number(1!=a)}},dz:{name:"Dzongkha",numbers:[1],plurals:function(){return 0}},el:{name:"Greek",numbers:[1,2],plurals:function(a){return Number(1!=a)}},en:{name:"English",numbers:[1,2],plurals:function(a){return Number(1!=a)}},eo:{name:"Esperanto",numbers:[1,2],plurals:function(a){return Number(1!=a)}},es:{name:"Spanish",numbers:[1,2],plurals:function(a){return Number(1!=a)}},es_ar:{name:"Argentinean Spanish",numbers:[1,2],plurals:function(a){return Number(1!=a)}},et:{name:"Estonian",numbers:[1,2],plurals:function(a){return Number(1!=a)}},eu:{name:"Basque",numbers:[1,2],plurals:function(a){return Number(1!=a)}},fa:{name:"Persian",numbers:[1],plurals:function(){return 0}},fi:{name:"Finnish",numbers:[1,2],plurals:function(a){return Number(1!=a)}},fil:{name:"Filipino",numbers:[1,2],plurals:function(a){return Number(a>1)}},fo:{name:"Faroese",numbers:[1,2],plurals:function(a){return Number(1!=a)}},fr:{name:"French",numbers:[1,2],plurals:function(a){return Number(a>1)}},fur:{name:"Friulian",numbers:[1,2],plurals:function(a){return Number(1!=a)}},fy:{name:"Frisian",numbers:[1,2],plurals:function(a){return Number(1!=a)}},ga:{name:"Irish",numbers:[1,2,3,7,11],plurals:function(a){return Number(1==a?0:2==a?1:7>a?2:11>a?3:4)}},gd:{name:"Scottish Gaelic",numbers:[1,2,3,20],plurals:function(a){return Number(1==a||11==a?0:2==a||12==a?1:a>2&&20>a?2:3)}},gl:{name:"Galician",numbers:[1,2],plurals:function(a){return Number(1!=a)}},gu:{name:"Gujarati",numbers:[1,2],plurals:function(a){return Number(1!=a)}},gun:{name:"Gun",numbers:[1,2],plurals:function(a){return Number(a>1)}},ha:{name:"Hausa",numbers:[1,2],plurals:function(a){return Number(1!=a)}},he:{name:"Hebrew",numbers:[1,2],plurals:function(a){return Number(1!=a)}},hi:{name:"Hindi",numbers:[1,2],plurals:function(a){return Number(1!=a)}},hr:{name:"Croatian",numbers:[1,2,5],plurals:function(a){return Number(1==a%10&&11!=a%100?0:a%10>=2&&4>=a%10&&(10>a%100||a%100>=20)?1:2)}},hu:{name:"Hungarian",numbers:[1,2],plurals:function(a){return Number(1!=a)}},hy:{name:"Armenian",numbers:[1,2],plurals:function(a){return Number(1!=a)}},ia:{name:"Interlingua",numbers:[1,2],plurals:function(a){return Number(1!=a)}},id:{name:"Indonesian",numbers:[1],plurals:function(){return 0}},is:{name:"Icelandic",numbers:[1,2],plurals:function(a){return Number(1!=a%10||11==a%100)}},it:{name:"Italian",numbers:[1,2],plurals:function(a){return Number(1!=a)}},ja:{name:"Japanese",numbers:[1],plurals:function(){return 0}},jbo:{name:"Lojban",numbers:[1],plurals:function(){return 0}},jv:{name:"Javanese",numbers:[0,1],plurals:function(a){return Number(0!==a)}},ka:{name:"Georgian",numbers:[1],plurals:function(){return 0}},kk:{name:"Kazakh",numbers:[1],plurals:function(){return 0}},km:{name:"Khmer",numbers:[1],plurals:function(){return 0}},kn:{name:"Kannada",numbers:[1,2],plurals:function(a){return Number(1!=a)}},ko:{name:"Korean",numbers:[1],plurals:function(){return 0}},ku:{name:"Kurdish",numbers:[1,2],plurals:function(a){return Number(1!=a)}},kw:{name:"Cornish",numbers:[1,2,3,4],plurals:function(a){return Number(1==a?0:2==a?1:3==a?2:3)}},ky:{name:"Kyrgyz",numbers:[1],plurals:function(){return 0}},lb:{name:"Letzeburgesch",numbers:[1,2],plurals:function(a){return Number(1!=a)}},ln:{name:"Lingala",numbers:[1,2],plurals:function(a){return Number(a>1)}},lo:{name:"Lao",numbers:[1],plurals:function(){return 0}},lt:{name:"Lithuanian",numbers:[1,2,10],plurals:function(a){return Number(1==a%10&&11!=a%100?0:a%10>=2&&(10>a%100||a%100>=20)?1:2)}},lv:{name:"Latvian",numbers:[0,1,2],plurals:function(a){return Number(1==a%10&&11!=a%100?0:0!==a?1:2)}},mai:{name:"Maithili",numbers:[1,2],plurals:function(a){return Number(1!=a)}},mfe:{name:"Mauritian Creole",numbers:[1,2],plurals:function(a){return Number(a>1)}},mg:{name:"Malagasy",numbers:[1,2],plurals:function(a){return Number(a>1)}},mi:{name:"Maori",numbers:[1,2],plurals:function(a){return Number(a>1)}},mk:{name:"Macedonian",numbers:[1,2],plurals:function(a){return Number(1==a||1==a%10?0:1)}},ml:{name:"Malayalam",numbers:[1,2],plurals:function(a){return Number(1!=a)}},mn:{name:"Mongolian",numbers:[1,2],plurals:function(a){return Number(1!=a)}},mnk:{name:"Mandinka",numbers:[0,1,2],plurals:function(a){return Number(1==a?1:2)}},mr:{name:"Marathi",numbers:[1,2],plurals:function(a){return Number(1!=a)}},ms:{name:"Malay",numbers:[1],plurals:function(){return 0}},mt:{name:"Maltese",numbers:[1,2,11,20],plurals:function(a){return Number(1==a?0:0===a||a%100>1&&11>a%100?1:a%100>10&&20>a%100?2:3)}},nah:{name:"Nahuatl",numbers:[1,2],plurals:function(a){return Number(1!=a)}},nap:{name:"Neapolitan",numbers:[1,2],plurals:function(a){return Number(1!=a)}},nb:{name:"Norwegian Bokmal",numbers:[1,2],plurals:function(a){return Number(1!=a)}},ne:{name:"Nepali",numbers:[1,2],plurals:function(a){return Number(1!=a)}},nl:{name:"Dutch",numbers:[1,2],plurals:function(a){return Number(1!=a)}},nn:{name:"Norwegian Nynorsk",numbers:[1,2],plurals:function(a){return Number(1!=a)}},no:{name:"Norwegian",numbers:[1,2],plurals:function(a){return Number(1!=a)}},nso:{name:"Northern Sotho",numbers:[1,2],plurals:function(a){return Number(1!=a)}},oc:{name:"Occitan",numbers:[1,2],plurals:function(a){return Number(a>1)}},or:{name:"Oriya",numbers:[2,1],plurals:function(a){return Number(1!=a)}},pa:{name:"Punjabi",numbers:[1,2],plurals:function(a){return Number(1!=a)}},pap:{name:"Papiamento",numbers:[1,2],plurals:function(a){return Number(1!=a)}},pl:{name:"Polish",numbers:[1,2,5],plurals:function(a){return Number(1==a?0:a%10>=2&&4>=a%10&&(10>a%100||a%100>=20)?1:2)}},pms:{name:"Piemontese",numbers:[1,2],plurals:function(a){return Number(1!=a)}},ps:{name:"Pashto",numbers:[1,2],plurals:function(a){return Number(1!=a)}},pt:{name:"Portuguese",numbers:[1,2],plurals:function(a){return Number(1!=a)}},pt_br:{name:"Brazilian Portuguese",numbers:[1,2],plurals:function(a){return Number(1!=a)}},rm:{name:"Romansh",numbers:[1,2],plurals:function(a){return Number(1!=a)}},ro:{name:"Romanian",numbers:[1,2,20],plurals:function(a){return Number(1==a?0:0===a||a%100>0&&20>a%100?1:2)}},ru:{name:"Russian",numbers:[1,2,5],plurals:function(a){return Number(1==a%10&&11!=a%100?0:a%10>=2&&4>=a%10&&(10>a%100||a%100>=20)?1:2)}},sah:{name:"Yakut",numbers:[1],plurals:function(){return 0}},sco:{name:"Scots",numbers:[1,2],plurals:function(a){return Number(1!=a)}},se:{name:"Northern Sami",numbers:[1,2],plurals:function(a){return Number(1!=a)}},si:{name:"Sinhala",numbers:[1,2],plurals:function(a){return Number(1!=a)}},sk:{name:"Slovak",numbers:[1,2,5],plurals:function(a){return Number(1==a?0:a>=2&&4>=a?1:2)}},sl:{name:"Slovenian",numbers:[5,1,2,3],plurals:function(a){return Number(1==a%100?1:2==a%100?2:3==a%100||4==a%100?3:0)}},so:{name:"Somali",numbers:[1,2],plurals:function(a){return Number(1!=a)}},son:{name:"Songhay",numbers:[1,2],plurals:function(a){return Number(1!=a)}},sq:{name:"Albanian",numbers:[1,2],plurals:function(a){return Number(1!=a)}},sr:{name:"Serbian",numbers:[1,2,5],plurals:function(a){return Number(1==a%10&&11!=a%100?0:a%10>=2&&4>=a%10&&(10>a%100||a%100>=20)?1:2)}},su:{name:"Sundanese",numbers:[1],plurals:function(){return 0}},sv:{name:"Swedish",numbers:[1,2],plurals:function(a){return Number(1!=a)}},sw:{name:"Swahili",numbers:[1,2],plurals:function(a){return Number(1!=a)}},ta:{name:"Tamil",numbers:[1,2],plurals:function(a){return Number(1!=a)}},te:{name:"Telugu",numbers:[1,2],plurals:function(a){return Number(1!=a)}},tg:{name:"Tajik",numbers:[1,2],plurals:function(a){return Number(a>1)}},th:{name:"Thai",numbers:[1],plurals:function(){return 0}},ti:{name:"Tigrinya",numbers:[1,2],plurals:function(a){return Number(a>1)}},tk:{name:"Turkmen",numbers:[1,2],plurals:function(a){return Number(1!=a)}},tr:{name:"Turkish",numbers:[1,2],plurals:function(a){return Number(a>1)}},tt:{name:"Tatar",numbers:[1],plurals:function(){return 0}},ug:{name:"Uyghur",numbers:[1],plurals:function(){return 0}},uk:{name:"Ukrainian",numbers:[1,2,5],plurals:function(a){return Number(1==a%10&&11!=a%100?0:a%10>=2&&4>=a%10&&(10>a%100||a%100>=20)?1:2)}},ur:{name:"Urdu",numbers:[1,2],plurals:function(a){return Number(1!=a)}},uz:{name:"Uzbek",numbers:[1,2],plurals:function(a){return Number(a>1)}},vi:{name:"Vietnamese",numbers:[1],plurals:function(){return 0}},wa:{name:"Walloon",numbers:[1,2],plurals:function(a){return Number(a>1)}},wo:{name:"Wolof",numbers:[1],plurals:function(){return 0}},yo:{name:"Yoruba",numbers:[1,2],plurals:function(a){return Number(1!=a)}},zh:{name:"Chinese",numbers:[1],plurals:function(){return 0}}},addRule:function(a,b){M.rules[a]=b},setCurrentLng:function(a){if(!M.currentRule||M.currentRule.lng!==a){var b=a.split("-");M.currentRule={lng:a,rule:M.rules[b[0]]}}},get:function(a,b){function c(b,c){var d;if(d=M.currentRule&&M.currentRule.lng===a?M.currentRule.rule:M.rules[b]){var e=d.plurals(c),f=d.numbers[e];return 2===d.numbers.length&&1===d.numbers[0]&&(2===f?f=-1:1===f&&(f=1)),f}return 1===c?"1":"-1"}var d=a.split("-");return c(d[0],b)}},N={},O=function(a,b){N[a]=b},P=function(){function a(a){return Object.prototype.toString.call(a).slice(8,-1).toLowerCase()}function b(a,b){for(var c=[];b>0;c[--b]=a);return c.join("")}var c=function(){return c.cache.hasOwnProperty(arguments[0])||(c.cache[arguments[0]]=c.parse(arguments[0])),c.format.call(null,c.cache[arguments[0]],arguments)};return c.format=function(c,d){var e,f,g,h,i,j,k,l=1,m=c.length,n="",o=[];for(f=0;m>f;f++)if(n=a(c[f]),"string"===n)o.push(c[f]);else if("array"===n){if(h=c[f],h[2])for(e=d[l],g=0;g=0?"+"+e:e,j=h[4]?"0"==h[4]?"0":h[4].charAt(1):" ",k=h[6]-String(e).length,i=h[6]?b(j,k):"",o.push(h[5]?e+i:i+e)}return o.join("")},c.cache={},c.parse=function(a){for(var b=a,c=[],d=[],e=0;b;){if(null!==(c=/^[^\x25]+/.exec(b)))d.push(c[0]);else if(null!==(c=/^\x25{2}/.exec(b)))d.push("%");else{if(null===(c=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(b)))throw"[sprintf] huh?";if(c[2]){e|=1;var f=[],g=c[2],h=[];if(null===(h=/^([a-z_][a-z_\d]*)/i.exec(g)))throw"[sprintf] huh?";for(f.push(h[1]);""!==(g=g.substring(h[0].length));)if(null!==(h=/^\.([a-z_][a-z_\d]*)/i.exec(g)))f.push(h[1]);else{if(null===(h=/^\[(\d+)\]/.exec(g)))throw"[sprintf] huh?";f.push(h[1])}c[2]=f}else e|=2;if(3===e)throw"[sprintf] mixing positional and named placeholders is not (yet) supported";d.push(c)}b=b.substring(c[0].length)}return d},c}(),Q=function(a,b){return b.unshift(a),P.apply(null,b)};O("sprintf",function(a,b,c){return c.sprintf?"[object Array]"===Object.prototype.toString.apply(c.sprintf)?Q(a,c.sprintf):"object"==typeof c.sprintf?P(a,c.sprintf):a:a}),B.init=e,B.setLng=k,B.preload=f,B.addResourceBundle=g,B.loadNamespace=i,B.loadNamespaces=j,B.setDefaultNamespace=h,B.t=s,B.translate=s,B.exists=r,B.detectLanguage=K.detectLanguage,B.pluralExtensions=M,B.sync=L,B.functions=K,B.lng=l,B.addPostProcessor=O,B.options=G}(); \ No newline at end of file diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index 8184e184..44da3a85 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -1,4 +1,4 @@ -var ownProfileId = -1; +var ownProfileId = -1; var profileIdRequest = -1; var songIdRequest = -1; var allSongsCache = null; @@ -15,6 +15,7 @@ $(document).ready(function () { initLoginPageHandler(); initHeartbeat(); initVideoPopup(); + initTranslation(); }); function replaceTransitionHandler() { @@ -68,7 +69,7 @@ function initPageLoadHandler() { } else { dataToUpload["Password"] = null; } - + request({ url: "sendProfile", contentType: "application/json;charset=utf-8", @@ -90,7 +91,7 @@ function initPageLoadHandler() { "Avatar": { "base64Data": null }, "Difficulty": 0, "IsEditable": true, - "PlayerName": "YourName", + "PlayerName": i18n.t("YourName") || "YourName", "ProfileId": -1, "Type": 1 }); @@ -116,7 +117,7 @@ function initPageLoadHandler() { } else { dataToUpload["Password"] = null; } - + request({ url: "sendProfile", contentType: "application/json;charset=utf-8", @@ -184,8 +185,7 @@ function initPageLoadHandler() { //pageLoadHandler for selectProfile $(document).on('pagebeforeshow', '#selectProfile', function () { var promise = request({ - url: "getProfileList", - headers: { "session": sessionId } + url: "getProfileList" }).done(function (data) { $('#selectProfileList').children().remove(); @@ -213,8 +213,7 @@ function initPageLoadHandler() { //pageLoadHandler for displaySong $(document).on('pagebeforeshow', '#displaySong', function () { var promise = request({ - url: "getSong?songId=" + songIdRequest, - headers: { "session": sessionId } + url: "getSong?songId=" + songIdRequest }).done(function (result) { $('#displaySongAddPlaylist').hide(); @@ -336,8 +335,7 @@ function initPageLoadHandler() { //pageLoadHandler for selectUserAdmin $(document).on('pagebeforeshow', '#selectUserAdmin', function () { var promise = request({ - url: "getProfileList", - headers: { "session": sessionId } + url: "getProfileList" }).done(function (data) { $('#selectUserAdminList').children().remove(); @@ -362,8 +360,7 @@ function initPageLoadHandler() { //pageLoadHandler for displayUserAdmin $(document).on('pagebeforeshow', '#displayUserAdmin', function () { var promise = request({ - url: "getUserRole?profileId=" + profileIdRequest, - headers: { "session": sessionId } + url: "getUserRole?profileId=" + profileIdRequest }).done(function (result) { $('#roleAdministrator').prop("checked", ((result & 0x01) != 0)).checkboxradio("refresh"); @@ -459,7 +456,7 @@ function initPageLoadHandler() { + '"> '/*+' '*/ + '

        ' + data[id].PlaylistName + '

        ' + data[id].SongCount - + ' songs

        Delete ') + + ' ' + i18n.t('songs') + '

        Delete ') .appendTo('#selectPlaylistContentList'); line.find('a:not(.delete)').click(handleSelectSongLineClick); line.find('a.delete').click(handleSelectSongLineDeleteClick); @@ -492,7 +489,7 @@ function initPageLoadHandler() { }); }); } else { - alert("This is not a name."); + alert(i18n.t("This is not a valid name.")); } }); @@ -907,6 +904,9 @@ function request(data, message) { } if (message != "noOverlay") { + if (i18n.t) { + message = i18n.t(message) || message; + } $('div[data-role="content"]').wrap('
        '); $.mobile.loading('show', { text: message, @@ -920,6 +920,9 @@ function request(data, message) { if (message == "external") { message = "Loading (external)..."; + if (i18n.t) { + message = i18n.t(message) || message; + } } else { data["headers"]["session"] = sessionId; } @@ -949,6 +952,10 @@ function showError(message) { message = "Error..."; } + if (i18n.t) { + message = i18n.t(message) || message; + } + $('div[data-role="content"]').wrap('
        '); $.mobile.loading('show', { text: message, @@ -1059,4 +1066,167 @@ function showWikipedia(artist) { $("#popupVideo iframe").attr("src", "http://m.wikipedia.org/wiki/Special:Search/" + artist); $("#popupVideo").popup("open"); +} + +function initTranslation() { + var translations = { + "en": { + translation: { + 'loginName': 'User:', + 'loginPassword': 'Password:', + 'loginButton': 'Login', + 'registerButton': 'Create Profile', + '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...', + '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' + } + }, + "de": { + translation: { + 'loginName': 'Benutzer:', + 'loginPassword': 'Passwort:', + 'loginButton': 'Einloggen', + 'registerButton': 'Erstelle Profil', + '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...', + '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' + } + } + }; + $.i18n.init({ + resStore: translations, + lng: "de", + fallbackLng: 'en', + debug: true + }).done(function () { + $('body').i18n(); + }); } \ No newline at end of file From 35709fd5d1d23d45fb91162798cf80d6b1c01e79 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 17 Nov 2013 19:28:52 +0100 Subject: [PATCH 52/81] Websever: add a page to enter serveraddress for usage in apps --- .../ClientServerLib/CWebservice.cs | 5 + .../ClientServerLib/ICWebservice.cs | 6 + Vocaluxe/Website/index.html | 572 +++++++++--------- Vocaluxe/Website/js/main.js | 75 ++- 4 files changed, 373 insertions(+), 285 deletions(-) diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs index 8c6f9302..ec51c0da 100644 --- a/ClientServerLib/ClientServerLib/CWebservice.cs +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -257,6 +257,11 @@ namespace ServerLib return CServer.GetDelayedImage(id); } + public bool IsServerOnline() + { + return true; + } + #endregion #region songs diff --git a/ClientServerLib/ClientServerLib/ICWebservice.cs b/ClientServerLib/ClientServerLib/ICWebservice.cs index 92e1a76a..c272915f 100644 --- a/ClientServerLib/ClientServerLib/ICWebservice.cs +++ b/ClientServerLib/ClientServerLib/ICWebservice.cs @@ -97,6 +97,12 @@ namespace ServerLib UriTemplate = "/delayedImage?id={id}")] CBase64Image GetDelayedImage(String id); + [OperationContract] + [WebInvoke(Method = "GET", + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/isServerOnline")] + bool IsServerOnline(); + #endregion #region songs diff --git a/Vocaluxe/Website/index.html b/Vocaluxe/Website/index.html index 44643218..4d0edef6 100644 --- a/Vocaluxe/Website/index.html +++ b/Vocaluxe/Website/index.html @@ -12,321 +12,335 @@ - -
        + +
        -

        Login

        +

        -
        - - - - -
        - -
        -
        -
        - +
        + + +
        +
        +
        +

        Login

        +
        + -
        -
        -

        Volcaluxe

        +
        + + + + +
        + +
        +
        +
        + +
        +
        - + -
        - +
        +
        +

        Volcaluxe

        +
        + + + +
        - -
        - + -
        -
        -

        +
        +
        +

        +
        + + +
        +
          +
          +
          - + -
          -
            +
            +
            +

            Profile

            +
            + + +
            + Avatar + + + + + + + + + + + +
            + +
            +
            - -
            - + -
            -
            -

            Profile

            -
            - +
            +
            +

            +
            + -
            - Avatar - - - - - - - - - - - -
            - -
            - -
            - - -
            -
            -

            -
            - - -
            - Cover -
            -
            -
            - - - -
            - - - -
            - - - -
            - - - -
            - - - -
            -
            - - -
            - - -
            - -
            - - -
            -
            -

            -
            - - -
            -
              -
              - -
              - - -
              -
              -

              -
              - - -
              -
              -
              -
              - -
              -
              -
              - -
              -
              -
              -
              - -
              -
              -
              - -
              -
              + +
              + +
              -
              -
              - + +
              + + +
              +
              +

              +
              + + +
              +
                +
                + +
                + + +
                +
                +

                +
                + + +
                +
                +
                +
                + +
                +
                +
                + +
                +
                +
                +
                + +
                +
                +
                + +
                +
                -
                - +
                +
                + +
                +
                + +
                +
                + +
                -
                - +
                + +
                -
                - - + +
                + + +
                +
                +

                -
                - -
                - + -
                -
                -

                +
                +
                  +
                  +
                  - + -
                  -
                    +
                    +
                    +

                    +
                    + + +
                    +
                    + + + + + +
                    + +
                    +
                    - -
                    - + -
                    -
                    -

                    +
                    +
                    +

                    + +
                    + + +
                    +
                      +
                      +
                      - + -
                      -
                      - - - - - -
                      - +
                      +
                      +

                      + +
                      + + +
                      +
                        +
                        +
                        - -
                        - + -
                        -
                        -

                        - -
                        - - -
                        -
                          -
                          - -
                          - - -
                          -
                          -

                          - -
                          - - -
                          -
                            -
                            - -
                            - - -
                            - +
                            + diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index 44da3a85..26e1c859 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -6,6 +6,7 @@ var playlistIdRequest = -1; var playlistRequestName = ""; var customSelectPlaylistSongCallback = null; var sessionId = ""; +var serverBaseAddress = ""; $(document).ready(function () { replaceTransitionHandler(); @@ -42,6 +43,9 @@ function replaceTransitionHandler() { } function initPageLoadHandler() { + //pageLoadHandler for discover + $(document).on('pagebeforeshow', '#discover', pagebeforeshowDiscover); + //pageLoadHandler for displayProfile $(document).on('pagebeforeshow', '#displayProfile', function () { if (profileIdRequest >= 0) { @@ -677,6 +681,26 @@ function pagebeforeshowLogin() { } } +function pagebeforeshowDiscover() { + if (document.location.protocol == "file:") { + if (window.localStorage) { + var address = window.localStorage.getItem("VocaluxeServerAddress"); + if (address != null) { + var prom = request({ url: address + "isServerOnline" }, "Checking...").done(function () { + serverBaseAddress = address; + window.localStorage.getItem("VocaluxeServerAddress", address); + $.mobile.changePage("#login", { transition: "none" }); + }); + $(this).data('promise', prom); + return; + } + } + + } else { + $.mobile.changePage("#login", { transition: "none" }); + } +} + function initLoginPageHandler() { var keyPressed = function (e) { if (e.which == 13) { @@ -715,7 +739,7 @@ function initLoginPageHandler() { }); //Fire pageLoadHandler for login - pagebeforeshowLogin(); + //pagebeforeshowLogin(); } function initMainPageHandler() { @@ -826,6 +850,37 @@ function initKeyboardPageHandler() { }); } +function initLoginPageHandler() { + var keyPressed = function (e) { + if (e.which == 13) { + $('#discoverConnect').click(); + } + }; + + $('#discoverServerAddress').keypress(keyPressed); + + $('#discoverConnect').click(function () { + var address = $('#discoverServerAddress').prop("value"); + if (address != null && address != "") { + if (address.indexOf("http") != 0) { + address = "http://" + address; + } + if (address.slice(-1) != '/') { + address = address + '/'; + } + request({ url: address + "isServerOnline" }, "Checking...").done(function () { + serverBaseAddress = address; + window.localStorage.getItem("VocaluxeServerAddress", address); + $.mobile.changePage("#login", { transition: "slidefade" }); + }); + } + }); + + //Fire pageLoadHandler for discover (first page shown after start) + pagebeforeshowDiscover(); + $(this).removeData('promise'); +} + var cachedImages = {}; function delayedImageLoad(elem, id, fail) { @@ -880,7 +935,7 @@ function logout() { function checkSession() { if (ownProfileId == -1 && profileIdRequest == -1 - && ($.mobile.activePage.attr("id") == "displayProfile" || $.mobile.activePage.attr("id") == "login")) { + && ($.mobile.activePage.attr("id") == "displayProfile" || $.mobile.activePage.attr("id") == "login" || $.mobile.activePage.attr("id") == "discover")) { return; } request({ @@ -925,6 +980,7 @@ function request(data, message) { } } else { data["headers"]["session"] = sessionId; + data.url = serverBaseAddress + data.url; } return $.ajax(data).always(function (result) { @@ -1142,7 +1198,11 @@ function initTranslation() { 'This is not a valid name.': 'This is not a valid name.', 'Uploading profile...': 'Uploading profile...', 'songs': 'songs', - 'YourName': 'YourName' + 'YourName': 'YourName', + 'discoverConnectHeader': 'Connect to server', + 'discoverConnectServerAddress': 'Serveraddress:', + 'discoverConnectButton': 'Connect', + 'Checking...': 'Checking...' } }, "de": { @@ -1217,15 +1277,18 @@ function initTranslation() { 'This is not a valid name.': 'Dies ist kein gültiger Name.', 'Uploading profile...': 'Profil hochladen...', 'songs': 'Lieder', - 'YourName': 'DeinName' + 'YourName': 'DeinName', + 'discoverConnectHeader': 'Verbinde zum Server', + 'discoverConnectServerAddress': 'Serveradresse:', + 'discoverConnectButton': 'Verbinden', + 'Checking...': 'Prüfen...' } } }; $.i18n.init({ resStore: translations, lng: "de", - fallbackLng: 'en', - debug: true + fallbackLng: 'en' }).done(function () { $('body').i18n(); }); From 86d0a245bfd0d51ff06a6c3723ea89638a25aaac Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 17 Nov 2013 20:13:55 +0100 Subject: [PATCH 53/81] Webserver: -fix: exception while uploading a photo if folder does not exits --- Vocaluxe/Base/Server/CVocaluxeServer.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index d750b673..380fe414 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -722,6 +722,11 @@ namespace Vocaluxe.Base.Server 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)) { From a91def2ff84bd3935f40874702df8a2e415cceb7 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 17 Nov 2013 20:27:16 +0100 Subject: [PATCH 54/81] Webserver: -fix: Not allowed if you edit your own profile --- ClientServerLib/ClientServerLib/CWebservice.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs index ec51c0da..7a6d4a3d 100644 --- a/ClientServerLib/ClientServerLib/CWebservice.cs +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -81,8 +81,8 @@ namespace ServerLib if (profile.ProfileId != -1) //-1 is the id for a new profile { - if (!(_CheckRight(EUserRights.EditAllProfiles) - || CSessionControl.GetUserIdFromSession(sessionKey) == profile.ProfileId)) + if (CSessionControl.GetUserIdFromSession(sessionKey) != profile.ProfileId + && !(_CheckRight(EUserRights.EditAllProfiles) )) { return; } From a8c5022bb065e53ec84b40509c15b1dddea15778 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 17 Nov 2013 20:28:30 +0100 Subject: [PATCH 55/81] Webserver: -mod: prepare for phonegap -> use the camera object --- Vocaluxe/Website/js/main.js | 114 ++++++++++++++++++++++++------------ 1 file changed, 78 insertions(+), 36 deletions(-) diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index 26e1c859..c3a523ab 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -10,13 +10,14 @@ var serverBaseAddress = ""; $(document).ready(function () { replaceTransitionHandler(); + initTranslation(); initPageLoadHandler(); initKeyboardPageHandler(); initMainPageHandler(); + initDiscoverPageHandler(); initLoginPageHandler(); initHeartbeat(); initVideoPopup(); - initTranslation(); }); function replaceTransitionHandler() { @@ -157,22 +158,40 @@ function initPageLoadHandler() { $('#captureContainer').remove(); } - $(document.body).append('
                            '); + if (document.location.protocol == "file:" + && typeof(navigator) != 'undefined' + && typeof(navigator.camera) != 'undefined' + && typeof(navigator.camera.getPicture) != 'undefined') { + navigator.camera.getPicture(function (imageData) { + $('#playerAvatar').prop("src", "data:image/jpeg;base64," + imageData); + $('#playerAvatar').data("changed", true); + }, function() { + //Fail - do nothing + }, { + destinationType: Camera.DestinationType.DATA_URL, + allowEdit: true, + correctOrientation: true, + saveToPhotoAlbum: true + }); - $('#capture').change(function (eventData) { - if (eventData && eventData.target && eventData.target.files && eventData.target.files.length == 1) { - var file = eventData.target.files[0]; - var reader = new FileReader(); - reader.onloadend = function (e) { - $('#playerAvatar').prop("src", e.target.result); - $('#playerAvatar').data("changed", true); - $('#captureContainer').remove(); - }; - reader.readAsDataURL(file); - } - }); + } else { + $(document.body).append('
                            '); - $('#capture').click(); + $('#capture').change(function(eventData) { + if (eventData && eventData.target && eventData.target.files && eventData.target.files.length == 1) { + var file = eventData.target.files[0]; + var reader = new FileReader(); + reader.onloadend = function(e) { + $('#playerAvatar').prop("src", e.target.result); + $('#playerAvatar').data("changed", true); + $('#captureContainer').remove(); + }; + reader.readAsDataURL(file); + } + }); + + $('#capture').click(); + } }); } else { @@ -758,33 +777,54 @@ function initMainPageHandler() { }); }); + function uploadImg(imgData) { + request({ + url: "sendPhoto", + contentType: "application/json;charset=utf-8", + type: "POST", + data: JSON.stringify({ Photo: { base64Data: imgData } }) + }, 'Uploading photo...'); + } + $('#mainPageTakePhotoLink').click(function () { if ($('#captureContainer').length > 0) { $('#captureContainer').remove(); } - $(document.body).append('
                            '); + if (document.location.protocol == "file:" + && typeof (navigator) != 'undefined' + && typeof (navigator.camera) != 'undefined' + && typeof (navigator.camera.getPicture) != 'undefined') { + navigator.camera.getPicture(function (imageData) { + uploadImg("data:image/jpeg;base64," + imageData); + }, function () { + //Fail - do nothing + }, { + destinationType: Camera.DestinationType.DATA_URL, + allowEdit: true, + correctOrientation: true, + saveToPhotoAlbum: true + }); - $('#capture').change(function (eventData) { - if (eventData && eventData.target && eventData.target.files && eventData.target.files.length == 1) { - var file = eventData.target.files[0]; - var reader = new FileReader(); + } else { + $(document.body).append('
                            '); - reader.onloadend = function (e) { - request({ - url: "sendPhoto", - contentType: "application/json;charset=utf-8", - type: "POST", - headers: { "session": sessionId }, - data: JSON.stringify({ Photo: { base64Data: e.target.result } }) - }, 'Uploading photo...'); - }; + $('#capture').change(function (eventData) { + if (eventData && eventData.target && eventData.target.files && eventData.target.files.length == 1) { + var file = eventData.target.files[0]; + var reader = new FileReader(); - reader.readAsDataURL(file); - } - }); + reader.onloadend = function (e) { + uploadImg(e.target.result); + $('#capture').remove(); + }; - $('#capture').click(); + reader.readAsDataURL(file); + } + }); + + $('#capture').click(); + } }); $('#mainPageLogoutLink').click(function () { @@ -850,7 +890,7 @@ function initKeyboardPageHandler() { }); } -function initLoginPageHandler() { +function initDiscoverPageHandler() { var keyPressed = function (e) { if (e.which == 13) { $('#discoverConnect').click(); @@ -877,8 +917,10 @@ function initLoginPageHandler() { }); //Fire pageLoadHandler for discover (first page shown after start) - pagebeforeshowDiscover(); - $(this).removeData('promise'); + setTimeout(function() { + pagebeforeshowDiscover(); + $(this).removeData('promise'); + },1); } var cachedImages = {}; From 334340cf1fcea6e3cbbe321b86738c3cc51dda12 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 17 Nov 2013 20:43:20 +0100 Subject: [PATCH 56/81] Webserver: -mod: changed assembly name of WebserverInitalConfig to VocaluxeServerConfig and add an icon --- .../Properties/AssemblyInfo.cs | 8 ++++---- WebserverInitalConfig/Vocaluxe.ico | Bin 0 -> 89378 bytes .../WebserverInitalConfig.csproj | 8 +++++++- 3 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 WebserverInitalConfig/Vocaluxe.ico diff --git a/WebserverInitalConfig/Properties/AssemblyInfo.cs b/WebserverInitalConfig/Properties/AssemblyInfo.cs index 18b96b78..4b7d7a28 100644 --- a/WebserverInitalConfig/Properties/AssemblyInfo.cs +++ b/WebserverInitalConfig/Properties/AssemblyInfo.cs @@ -5,11 +5,11 @@ 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("WebserverInitalConfig")] -[assembly: AssemblyDescription("")] +[assembly: AssemblyTitle("Vocaluxe Server Config")] +[assembly: AssemblyDescription("Configures your computer to run the Vocaluxe Server")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("WebserverInitalConfig")] +[assembly: AssemblyCompany("Vocaluxe")] +[assembly: AssemblyProduct("Vocaluxe Server Config")] [assembly: AssemblyCopyright("Copyright © 2013")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/WebserverInitalConfig/Vocaluxe.ico b/WebserverInitalConfig/Vocaluxe.ico new file mode 100644 index 0000000000000000000000000000000000000000..aeb8dec97757f83a40000d2ee0cd3e453e5de744 GIT binary patch literal 89378 zcmeFZcUV=w(kL7{RulmN3n)z~(mMz!NH0>Q_geoC2KlD}xO@Uj|2s|$Kr0oN{wQum0D!|) zC=db;paqY&0T^cb!%qwH833@k3Ug?W^7A1dsSM6Wt!yN z!T$&y-v9H(A7;W7fBz!{ukaQIf6&<22r~{2|G>ck_6`R4!zN)b{|UIa{X44QR#fZ% znjRX0YH!1Y{%c0)!Fn48gADzbjOc^S2#g(a&f}jmhz~Xog4Wu}?s}xp5m7>(Soo>I(~S=XW|Pm?V0G-`pKG+Kf{> zYTj4N&B^1C9&(wx*kR@|Zl(^9-qI975{;D;y19bjZ=XjY-l^z)hXrWemN~2_l!lPD zY+pdR^0^}-LS_*N5|2$RJxq7^jcT90Epf-!7ZYsBaP$D7(f;@C=G*7nj7_E6+dVJ{ zHLHVYNbeWA;%?;|rnLKhZ1HjmPYJy5VV2v;5i z4?i*j@*Y+P0Hhtl7m7KLa6!0PF3kHPkJ1TY_qDZIN?ST>YB9M&`X~>qbfQLLJ0vpr zHi8#{;Ma1un)gMtW78w%+ler9p(;-9yr$C58kW8x3k%qE2dI1qRC_2;yY1$z!h~FC zM;wkO*n!CT2#?TBcSwYYUWeoh{#behX1>*B_i9-GlH{YW#3VLD;N0ty)c zZ-_lSLLmAB#Mnk|{}cNgjzD6N{(p=AbsOsOZVk z#IX6h0FYoY>@y-Po`QA}iyNUhEcS=k?{64JffxY$SWNQ|48=e}0Q|vF925w^e}z|m z=O1D`0RCJ2-^lqR|4+Gp@Spk}#$i1V>0rI*u;oJB=>Hr4iDNOOYy5W@K35}7BRE(F zU(D~&Vm0P{NbbmbKtykh~O38{-4Y< z#CCR2-d_-k!~{qG6$8-+s5X?xk&ePtXrJwTTmP6@04E7|R4dZzw-Uo_f21!QoA-_k zJ@LT?kwaU%Wt-`doh3PNLP%pUn0aZLO@FMk4Fnv2me8>9A2MvNxbnfl=WA*16bkD= zeBh5j&duv#FbHF86^Nq|2un`LLpswEEh2D#8~;!M5xgD+qd;1qO?e`@lf|rjH{FD zOiL?J`rq`A2n(%#kxh<&3XqTn2`dDOVjjb@A%dm8w3Brp)cr@{ujssAASrX_;3B#pm=Kg2K)9R?1fgGRrD zgQ>%U4-T#YxJHA47KT51?ho((J@`YVhB;8V4-ve=+y7Y4p&5Wc5{!a8&>}@(ux&;X zVu3`!evNiT&bN60u)#Nvvb6FCA)0M=!CL;r!M+jh7=%A@kY%%Us3lBauyjXx_=DgG zgqBCIKS0jA^E-rslk;u&r4blFJns=5x)BA##f5=|I4f|LVh84T_<)x@ zH*iuB1GjG70`l_mKt)O%sLI?1>gwu1PeT>x>gobh4JF{KCkIS*HG!?J8n7_b1GXmm zz|TkpIGN}IGcz+_V`c(utt^0zjSX;ib_SlFo*+}B>+-%g+Z|f1ISco0p*%kLHRufP^(7|Y7DM}JUw1e zZ*(0L8VQ1GYcbHGLj&6NFN1Ew%b?%nG8i(a0Uxa{g9+Tmll@gN;YbI@9O%J_ z6BGFC%m7C2UjrXquY(p#PS9+@12GTiwBrKrZG=F(tsrQ(hrvM<^xo$NA6$9Bpa&oL zLjuMn7apaoxD=)jx@1DHl!17DHMV8Q1acyRAF2-m$09_q`1Cq|MW#q
                             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%0D>r^)KQ9waC2K)05MD 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 Properties WebserverInitalConfig - WebserverInitalConfig + VocaluxeServerConfig v4.0 512 @@ -35,6 +35,9 @@ app.manifest + + Vocaluxe.ico + False @@ -69,6 +72,9 @@ Designer + + +
                            - - - - + + \ No newline at end of file diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index c3a523ab..39760925 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -8,7 +8,21 @@ var customSelectPlaylistSongCallback = null; var sessionId = ""; var serverBaseAddress = ""; -$(document).ready(function () { +if (document.location.protocol == "file:") { + if(typeof (window.deviceAndJqmLoaded) == "undefined"){ + window.deviceAndJqmLoaded = $.Deferred(); + } + window.deviceAndJqmLoaded.done(function(){ + start(); + }) +} else { + $(document).ready(function () { + start(); + }); +} + + +function start() { replaceTransitionHandler(); initTranslation(); initPageLoadHandler(); @@ -18,7 +32,7 @@ $(document).ready(function () { initLoginPageHandler(); initHeartbeat(); initVideoPopup(); -}); +} function replaceTransitionHandler() { //Thx to http://stackoverflow.com/a/14096311 @@ -168,7 +182,7 @@ function initPageLoadHandler() { }, function() { //Fail - do nothing }, { - destinationType: Camera.DestinationType.DATA_URL, + destinationType: navigator.camera.DestinationType.DATA_URL, allowEdit: true, correctOrientation: true, saveToPhotoAlbum: true @@ -800,7 +814,7 @@ function initMainPageHandler() { }, function () { //Fail - do nothing }, { - destinationType: Camera.DestinationType.DATA_URL, + destinationType: navigator.camera.DestinationType.DATA_URL, allowEdit: true, correctOrientation: true, saveToPhotoAlbum: true From 8c7fdc050fce2f490be3e4f3ef07913b476752af Mon Sep 17 00:00:00 2001 From: lukeIam Date: Fri, 29 Nov 2013 20:13:57 +0100 Subject: [PATCH 59/81] Webserver: -mod: removed back buttons on discover and login page --- Vocaluxe/Website/index.html | 638 ++++++++++++++++++------------------ 1 file changed, 319 insertions(+), 319 deletions(-) diff --git a/Vocaluxe/Website/index.html b/Vocaluxe/Website/index.html index e22e9502..df58ae89 100644 --- a/Vocaluxe/Website/index.html +++ b/Vocaluxe/Website/index.html @@ -4,40 +4,40 @@ Vocaluxe - + - - - + + + - + - -
                            + +

                            @@ -51,318 +51,318 @@
                            -
                            -
                            -

                            Login

                            -
                            - - -
                            - - - - -
                            -
                            -
                            -
                            -
                            - -
                            - +
                            +
                            +

                            Login

                            - + -
                            -
                            -

                            Volcaluxe

                            -
                            - - - - +
                            + + + + +
                            + +
                            +
                            +
                            +
                            - + +
                            + -
                            -
                            -

                            -
                            - - -
                            -
                              -
                              - +
                              +
                              +

                              Volcaluxe

                              - + -
                              -
                              -

                              Profile

                              -
                              - - -
                              - Avatar - - - - - - - - - - - -
                              - -
                              - + - + +
                              + -
                              -
                              -

                              +
                              +
                              +

                              +
                              + + +
                              +
                                +
                                + +
                                + + +
                                +
                                +

                                Profile

                                +
                                + + +
                                + Avatar + + + + + + + + + + + +
                                + +
                                + +
                                + + +
                                +
                                +

                                +
                                + + +
                                + Cover +
                                +
                                +
                                + + - +
                                + + - +
                                + + - +
                                + + - +
                                + + - +
                                +
                                + - -
                                - Cover -
                                -
                                -
                                - - - -
                                - - - -
                                - - - -
                                - - - -
                                - - - -
                                -
                                - + +
                                + + +
                                + +
                                + + +
                                +
                                +

                                +
                                + + +
                                +
                                  +
                                  + +
                                  + + +
                                  +
                                  +

                                  +
                                  + + +
                                  +
                                  +
                                  +
                                  +
                                  - -
                                  - -
                                  - - -
                                  - -
                                  - - -
                                  -
                                  -

                                  -
                                  - - -
                                  -
                                    -
                                    - -
                                    - - -
                                    -
                                    -

                                    -
                                    - - -
                                    -
                                    -
                                    -
                                    - -
                                    -
                                    -
                                    - -
                                    -
                                    -
                                    -
                                    - -
                                    -
                                    -
                                    - -
                                    -
                                    +
                                    +
                                    +
                                    -
                                    -
                                    - -
                                    -
                                    - -
                                    -
                                    - -
                                    +
                                    -
                                    - - +
                                    + +
                                    +
                                    +
                                    + +
                                    +
                                    +
                                    +
                                    +
                                    + +
                                    +
                                    + +
                                    +
                                    +
                                    - +
                                    + + +
                                    - + +
                                    + -
                                    -
                                    -

                                    -
                                    - - -
                                    -
                                      -
                                      - +
                                      +
                                      +

                                      - + -
                                      -
                                      -

                                      -
                                      - - -
                                      -
                                      - - - - - -
                                      - -
                                      - +
                                      +
                                        - + +
                                        + -
                                        -
                                        -

                                        - -
                                        - - -
                                        -
                                          -
                                          - +
                                          +
                                          +

                                          - + -
                                          -
                                          -

                                          - -
                                          - - -
                                          -
                                            -
                                            - +
                                            +
                                            + + + + + +
                                            +
                                            - + +
                                            + -
                                            - - \ No newline at end of file +
                                            +
                                            +

                                            + +
                                            + + +
                                            +
                                              +
                                              + +
                                              + + +
                                              +
                                              +

                                              + +
                                              + + +
                                              +
                                                +
                                                + +
                                                + + +
                                                + + From 57770da524760767aacbbf05af3401136fbbf5b8 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Fri, 29 Nov 2013 20:15:52 +0100 Subject: [PATCH 60/81] Webserver: -fixe: photo quality is bad (using phonegap) --- Vocaluxe/Website/js/main.js | 44 +++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index 39760925..8d7033da 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -8,18 +8,18 @@ var customSelectPlaylistSongCallback = null; var sessionId = ""; var serverBaseAddress = ""; -if (document.location.protocol == "file:") { - if(typeof (window.deviceAndJqmLoaded) == "undefined"){ - window.deviceAndJqmLoaded = $.Deferred(); - } - window.deviceAndJqmLoaded.done(function(){ - start(); - }) +if (document.location.protocol == "file:") { + if (typeof (window.deviceAndJqmLoaded) == "undefined") { + window.deviceAndJqmLoaded = $.Deferred(); + } + window.deviceAndJqmLoaded.done(function () { + start(); + }); } else { - $(document).ready(function () { - start(); - }); -} + $(document).ready(function () { + start(); + }); +} function start() { @@ -173,29 +173,30 @@ function initPageLoadHandler() { } if (document.location.protocol == "file:" - && typeof(navigator) != 'undefined' - && typeof(navigator.camera) != 'undefined' - && typeof(navigator.camera.getPicture) != 'undefined') { + && typeof (navigator) != 'undefined' + && typeof (navigator.camera) != 'undefined' + && typeof (navigator.camera.getPicture) != 'undefined') { navigator.camera.getPicture(function (imageData) { $('#playerAvatar').prop("src", "data:image/jpeg;base64," + imageData); $('#playerAvatar').data("changed", true); - }, function() { + }, function () { //Fail - do nothing }, { destinationType: navigator.camera.DestinationType.DATA_URL, allowEdit: true, correctOrientation: true, - saveToPhotoAlbum: true + saveToPhotoAlbum: true, + quality: 50 }); } else { $(document.body).append('
                                                '); - $('#capture').change(function(eventData) { + $('#capture').change(function (eventData) { if (eventData && eventData.target && eventData.target.files && eventData.target.files.length == 1) { var file = eventData.target.files[0]; var reader = new FileReader(); - reader.onloadend = function(e) { + reader.onloadend = function (e) { $('#playerAvatar').prop("src", e.target.result); $('#playerAvatar').data("changed", true); $('#captureContainer').remove(); @@ -817,7 +818,8 @@ function initMainPageHandler() { destinationType: navigator.camera.DestinationType.DATA_URL, allowEdit: true, correctOrientation: true, - saveToPhotoAlbum: true + saveToPhotoAlbum: true, + quality: 100 }); } else { @@ -931,10 +933,10 @@ function initDiscoverPageHandler() { }); //Fire pageLoadHandler for discover (first page shown after start) - setTimeout(function() { + setTimeout(function () { pagebeforeshowDiscover(); $(this).removeData('promise'); - },1); + }, 1); } var cachedImages = {}; From 8b6f461fe0a83919d2fe54f6e84f6f18c5820d5a Mon Sep 17 00:00:00 2001 From: lukeIam Date: Fri, 29 Nov 2013 21:25:07 +0100 Subject: [PATCH 61/81] Webserver: -fix: serveraddess is not saved --- Vocaluxe/Website/js/main.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index 8d7033da..7eb0f330 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -722,14 +722,13 @@ function pagebeforeshowDiscover() { if (address != null) { var prom = request({ url: address + "isServerOnline" }, "Checking...").done(function () { serverBaseAddress = address; - window.localStorage.getItem("VocaluxeServerAddress", address); + window.localStorage.setItem("VocaluxeServerAddress", address); $.mobile.changePage("#login", { transition: "none" }); }); $(this).data('promise', prom); return; } } - } else { $.mobile.changePage("#login", { transition: "none" }); } @@ -924,11 +923,15 @@ function initDiscoverPageHandler() { if (address.slice(-1) != '/') { address = address + '/'; } - request({ url: address + "isServerOnline" }, "Checking...").done(function () { - serverBaseAddress = address; - window.localStorage.getItem("VocaluxeServerAddress", address); - $.mobile.changePage("#login", { transition: "slidefade" }); - }); + request({ url: address + "isServerOnline" }, "Checking...") + .done(function () { + serverBaseAddress = address; + window.localStorage.setItem("VocaluxeServerAddress", address); + $.mobile.changePage("#login", { transition: "slidefade" }); + }) + .fail(function () { + $('#discoverServerAddress').prop("value", ""); + }); } }); From 4019cc1dcf8c04fe8bce211b03840bc40a9000fb Mon Sep 17 00:00:00 2001 From: lukeIam Date: Fri, 29 Nov 2013 22:06:16 +0100 Subject: [PATCH 62/81] Webserver: -fix: error if the dicovery scrren is visited twice in a session --- Vocaluxe/Website/js/main.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index 7eb0f330..f34c6ee4 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -720,6 +720,7 @@ function pagebeforeshowDiscover() { if (window.localStorage) { var address = window.localStorage.getItem("VocaluxeServerAddress"); if (address != null) { + serverBaseAddress = ""; var prom = request({ url: address + "isServerOnline" }, "Checking...").done(function () { serverBaseAddress = address; window.localStorage.setItem("VocaluxeServerAddress", address); @@ -923,6 +924,7 @@ function initDiscoverPageHandler() { if (address.slice(-1) != '/') { address = address + '/'; } + serverBaseAddress = ""; request({ url: address + "isServerOnline" }, "Checking...") .done(function () { serverBaseAddress = address; From 3550b4eeb1265980223f38eb249eeba955bc3fe9 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sat, 30 Nov 2013 21:04:48 +0100 Subject: [PATCH 63/81] Webserver: -fix: appcrash if a given server is not reachable -add: scan a qrcode to insert server address (in app) -mod: own folder for phonegap build + created config.xml --- PhoneGap/config.xml | 61 ++++++++++++++++++++++++++++++++++++ PhoneGap/icon.png | Bin 0 -> 30639 bytes Vocaluxe/Vocaluxe.csproj | 3 ++ Vocaluxe/Website/index.html | 5 +++ Vocaluxe/Website/js/main.js | 46 ++++++++++++++++++++++++--- 5 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 PhoneGap/config.xml create mode 100644 PhoneGap/icon.png diff --git a/PhoneGap/config.xml b/PhoneGap/config.xml new file mode 100644 index 00000000..802cde2f --- /dev/null +++ b/PhoneGap/config.xml @@ -0,0 +1,61 @@ + + + + + + Vocaluxe + + + Interact with Vocaluxe via your mobile device. + + + + Vocaluxe Team + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PhoneGap/icon.png b/PhoneGap/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..43151bf67c1b51faf3ba039eab383d313e63d659 GIT binary patch literal 30639 zcmV)nK%KvdP)f1O+4zA}0xigc3pm z5rj}A=d3Jnwr6hLdTaIS-NN|HoOA5^<9?r>XFa`l@1WjY@2YyMR#mMkRsIk7JCT`1 zhZ0jMIyR9uM(w2V$n6xdc?X4U+)B$O^tcF21ox9+A$ejFQ@M2FLk zQdUmx!7Bgv??3y?y#Dam_QQ8*bHW|klyrl(rxeneYY(>le|;UD}q94 zUcd^PJZ(Nrni@dkr_Q6XljqPF9^?2ij-#f`p|Mlu%FyTWzKPT4(}ZaOJQncdg*0i# z0-7=_kfzLDK!HnxXkF+g+O{i(4j;*&3m0zH_`e9?zook_Q|ED~$jybpY{11`6Z<3s=<(ER8#viBU{N6v~8uIe;MkFStQ0Rsznzvvj3v)gTT?u~F#OXA8 z(p(xnaTWzEStUY@*u0Gn989E`1Bc{z=ui@6W}cy}tQe;g3TuPI7iR!D~Y{(w=>>l$w5wva_@4+O_L+<;qn#UcGvakJsq>_3L!)`W3ozouA*l zK{s#SlyU3UExLXCwjA%=xkGn(+`D_1?%lg5qp+}uE?mA$$4{N6LrDz8$Za%d{!-B( zlLZ`0XvVyy6coCVVh$$!{~H`@_unALzAXHnEOg&^1_BG+KT(eI7+Qjl_QqrVy1nsw zO`kXci(BtxS`%~izjd?n&YvH+Yu^D{vN~91=$J{fdFIcdDKqBLscW0HHxqTwKhfgaJ_^peQOWr_zdtR9afb1T>Gf?AS*$<}aa%vzIb3meYdeL9~%I zTVBDXf&b}!KYH#V#b@55l~LDd$&RbkWBM8LpO$4#K$vJH6Mo#2@2kHd6aNIdc>PO`e5#P>bAawx`vghv7y`?oi~)x$023(;hgj2_2n`C z5pe>l8ogM<_$yF#n{?{2ph#xhy>fMkkiAiC3IK)`K_PS??hxgjEuiz~FYvfTXD{G* zUd9D}d_kUHcmy0uYv{)SMSgxhWn^T~zJ2>BGIBF*-@cvsM1pXL%hxZ{t=l(#0}5?6 zG$4wKicCP1mX=a^dAS@PJSd}ziV7+#D`$|DQpU*>6c)aPrp{R`W6r$A?8)q*gw$L* zbm9(0#$KZZk>?1L&Ufl@YCAq%_?Vbq7I1B!WWMi;qlvb~c}yx6dM*Dra_kN*Y?y66 zI`|!?=0lGBIT~Wv>TLOExClA&1v&LirgvvtqAsCI=$%7L`Ee^Wxze!u5km7%_epO`JN1$=Yt7aXCDr&&fDq`| z83hFe>iN0z#<(a$gF+uMw5GsgXol$MXbM`lmbUNRMzN_e6rB*m+~5>lzH*Un+`J|{ zLURcX3M&{CAc_S97yw3DS(yv~qT<_!4339%_ufNV792tCrZJ(ESq3jlG#N)rrwO@Ucx~wmxjvGn^6wm^q4Z@14OBl3837;?K^F<7hVg^JJ1A@WB z&)crPMP7qXh{mbucTi@5y-z%iU6D>J)~prp0OU}Buxl^nuo_n&I4{S7g7Y%)yx?q} z073($px`VYF9;ws2=G1}wT1v7aD;Z)v114AP1s9Gne1_7MANQ>os@DSxe~d2oOY(9b_H0Rn3H)7J}&oDfkSdg0ckoFv&48V8bYOwwGY-8{<(}6YmO*b%$fahJ^Qg_D8`LiF z26=~-Q}>8s@{K4X_x@~R{8PkK05Hq9U;X0&F>b|Ks_AQ}qn`2P*e8Wrue?K@)|XRz z%zg$#=g>kvvZh#nUj*KXxkQ)sr3{cVIer{mN*zO3i>xnJ8iPU7K2)9Wu=F0;_d6o$ z4I~vVY`2l|bS5`PfKb3f&plTl!p_UflYz&%xk@YK=H?10@EEUYAYdqdp*h9HN`Qcu z0YZt-ojG%c_9gD2HBqZ**2)<)V%j$pxg$aZe(&D>-*^|l(F_=6rNR{e1Zas0;SUdZ ze9Ic*0S#TAD?$fn5-s49s33&2Tv1+fDo$PcA>^X&=lwD-%m;kptxU>7V1xRB`F4P%Ji%XYpH8 zE>ef!BI>Z7fv~oWLBNk$GjwDSz+~V#w1T{c2ed>x1_|B+5C9k**Okd=&*rA{x*}>i z^|G>wGCShPiM^HBlrusa^H|{71^Il;6U_kA0Wjps^Rvd|Ttho(&7ib|jW^iL1Uw8q zw3l(?#tk}u`8=)JxSEDd8BEJVmb1CILq!aR`wRkTipLR24G5(f%BYl&DS8R@WLe=V#EcbHM>fApb5OX$OQtTFFhqZ*;=SNwH#ne^= zUP5h|3$!yd0)_~ixdKKf%>H$J3{`>$U@!y}42DiT+OqcOxVBVYcO7(+oS91~qM679 zGo8+6L)bin^Ug33awNC};p4H^5@J5`3k)rB)*zPWDrp8QkyJpqX2u~f00@``Xads& zu+SlVtE*`R0zja_fMZ!%u>u5}iQoxLh9NT>EvU@))4%Xn+FW(R}(vrHNQO z)MOjm?2DsxI{S=x6*&xqYz7AgGz0*kHH8L)<_j7K7bPBXK?SBPL8(WRZa(XR1prE@&=TGo z%Vapv`6e<{{0#gVw!8G8g zBat`)4AxM!8KyQsp#h?`h1MJ@0A(BSDqu2TCdwXsD{dw@#P_TnhA+t#Pe5V?{JWqX zAbbcDvt9v#%>(lR|4kJ<%9uBl3U?6Gu+ch71PtB6iv%11OPghPMI$H@njjwAiM-N3 z9uP^{h31a{>OguR%vM2#42BYF2>}Nc8GtA;HAkCuB}xmdQ`$pbUtg?1U}%=MYl`JF zEtlP+2E()Xh8+-f3NVPvC8{-^HXb;^gfH9B4EYxBpu7tkZ@6H(quN9O5CDJ`5C8$R z0UpQ2#ZgE|2(4PRik2^5PD6(drD4N{(eUBJW#I9M5hG~r+O@Q1%^KRWWeXiWdbCo! z0Ye3z7!VcZ^Z+E1wZcQz5)U8zNOy}Kkn4bCi7g<8VCQp)$=`YA4aG{hEM&h32EoP$ z79iLLK!Rb_8p1Oe2ml4Xqd9vW;sF|Q2t+Xd6zve6a7%;)w+Db|_)Q+QUR@%Zp$*UO zR%;lYK_&9I^=bykn)@PX4G27Ly%x{QWVByb&Y*zCD5H;p9#EsH1!UhVL8&_aAGM93 z3(Q8dFHMl{wg@)IVOi%G5|hYcV9r!DyUch(N=(=KmyHy=Qy@zJ|V(itF%PBAT}5L{Oy2i zRF~BzG>?N%ibN^l*2;ny|EO;kW>EUcJPHWUpm`gPiFU}($u-=|0@J-j48j_j1Q=AT z;UXm`C)1QEQ>aUqE+YJ@RjZ0{pLymP`rF_Bh8sqI`O9DAi1EY|PyFVb9{Qa1HGIdj z&pt~pzWAbmq;~Dv)T?(7TDoKjUAS04O7yTx1fk$=kxPRsD5A}d5k)1 zEO5mOFM+)iEz~2PJ{+D*yW%ovU*c(MJ6gr+r>xBo?U0kNGy?`S12lw=Nb2>A6DLkk zKtKR}^wCH3`s=ULOE0}70I&*H4*&qKz4_*wRI64kdHnR#Pt#LRJtfCiUU`KYHEJZ< z0m8?59RL3Jzl-*G-1k27^fLmGH)_=+Utd2OHhZ(!c1J&@^_)LRl@Px0g~$@o2oN~H z08IdZJPr_eO*90+gBZjHgHSSwcl#_=MR{5K)bxp^jmbCuJV1mc+?F3AISu@yT!v&) zg8&w6Km|2eP(q#o?E5kp8qP1G2J_4LTq%R4M2^-0Fu06o_jSNg5k81d4aC`f)mlcK zK1noZ{V~cokwv4IX0YnBg=Ygoj!Uco9)%{6Dmtkmk^lnCLGRwZMYvGy5T2gR5F&t4 zqecyKc6OGT4At-G=qPHxO`A53&vmn`ZxLuvUw{2I4IVsL-Ur|~IXQ_2Y1Qf@YTdfE0HkKk+VtFutZANME%U0IT9wr66a1Sy zth^-v5Kyq7eIu1d=((v>w1nSgHI(@%SK4D^nMpRar_r4?3^)h^QPAEs{8jA6Z{!XN zShbdpXJ-F-pwNpi5+C51>?wjTq=vH#$#V_>QAl+eBy|}WIA51R0AP5|y-Rh6Gok98 zD#F)`EgH>@1|?F^_LG#9euDbUNF_&K!!7ekrZ;;Y5>A0Qf6B2;%4WV$z?$J4n~1!# z=V|@Ab=0x*$6^-#{`Y5PR#thk3O)JclL7{)?FJ1R&|7c4B{LrCA6f#SfS@68Z*OlA zDrPt|3xp4FtzNyFnlx!5W(404Fx9VLpJvRMAt0(-x2}8!oCNQA@4ffgJowVvZ@*2i zGYFr3fr;s}&(RxiPgbjrekwN5WOTN;l;TR7nxV|l4CR%^@0ktxJbNTCHSfPi z*X&YqpH)omlWvgX7n!oaqBEtOc*uedKOeRvozgQDVT8GmoXZ}`=E9j?(Q7a`QDP2< zGqS1R{6&h3k7d_z7`<7w8vX5Aw&8zylDR+?dg||g6*B?54%H1C4^7ajRV#YqjWQDY z)BK&csH)+Oy!d(z+axm53O@|EDBJ;n@Yz&sY68EF#pEAVA?D(7z|i0kPb0!0m|@J( zhMt!1MF0;PeAKG5MF0F39X)x1<}Y1O0V_lP94#?B{Ia>`4m3LVJ4&9j%E)8peKrTI z1!k6#>x_HkIrARXonAs7!}3IpsdPH1|1`B=#e!}*EQR(Q%%pt>k5RjkX_CwVatRHh zZr~wu@i{Ci5V80Xi_%#$T%^G8lQd-XY!T2iFFd380R!O~R?T*fcJwN1fEQkPNwfe4 zG{PsJd_q1xJ|buc4?={tc>n$PY3$gs!Z{#p47>;00wBVwC!Sjecn4w;_>8Not9%CE zh3f(65Wi^C_9Lpw0C~MyRjSswpPIc!YGJ*vvSe0cz{S)8RzfckaQs)ALcbqCf_L%J z;%h4EX%KVpvg`N0qhEjhC;jrTe^OHFQJT9flvb_T^v8qZ!maOXAoWd>IDCy{TJ|

                                                |{0#U&=t}l`PB~YEC8G zq?p;-5+e6MEYA-d&Y^AFwo$WQL1f>C5&zdGSt~HB|9cgB@%ev{muG$I+O0FS`0#y` zEJA=Fh)b6)r4=hyke{EQa0GjMdzsCXCr_5RL2z)e@Bsh;=Av`w&J-FNDxq!w1||pb z27DIW;rQ|6axDM_&godh?Afzv*REYObLLDoNAFRMT8?DbIm*l@g_(SN>N(Sc(5hd1 z7C83Y%sgUqg*hs52n#R(3TT*SV++hY3V>nI!d&`={>6a!mHx@&=bwM31F>l|e?=ID zM(+CKK{0Yo9t$r`#o<|yj{Yg+KH;VS!F|GQa{655^+9zBDfCV>*5eOR@5yPDl$J?h zJJRW`FH!|iLQ)NqsY1GJDtf1=gb-h)0te1dr#Z9dP%Zc7RI|%=(J(K0__7=LIyuy? z#W%khwf?9zwe8TJKK=AlA$_p%qehLQS+i!*xN+m;hzKLp{ltkAY30h5!VwlOTuAGf zheSq3N?-}XjEahq_rh(3;NiJ|U;-o?Hf*4I^XAECkY0z+<1^42%a$#Z@5gcF%4IZQ z*gVrK6W6+Lilhbjg|kqxC?!Nv310IEO)71pv=R`kk;_i2?@6pizTa3VJC;{MKe1-` z*FXPBzy9(I{rKyT^z%Kl6tFy$qGJ#J@t|<-nWmCAB~Op-eZOPmFtmW|{Zmz7 zM9e~pnb6T_P#mq>eu@%~o)OZBg)!s;yy+J!F$YP_2e0`26xsDZCh7TVc|Cz#`Sn3V z#?otVRHK*c4^o;0ZfLiC^!5i`sYBQH)atz!eZuu{rb`R_3Op04GIdP z0RsleXTUK4lKuPl%lF~)9XocE*Sd7+%FhGHd(3_nZSA2r#M|s@%Iai9nZX%KZQOyi z27sZ>g?2sluxbX)AsSD}H3Efka{oGwJx0GU2>$i2U+C9={zyOl`V0O1&;N(D#19fm zU$uS{1+G|22}yr&UgfHo%O*h-p&P4`qPpM_^iZxOz%qR4Q95}%o92b5lY8Gpnfa*M zkc=ovlVbq&O((}8c?_&{;U@AOhI`hg|571m&%V)&?AmWun!{g3`@DSCi5aL-y9RTE z>QwX1H>kQ@P5OYj0cJJ016)m*2&i=z7Z;j3b*g{`rUaxAWz0&5tU>3APr)1LwP zL)AiabeZwg}hW*TsF*Vyl7HnQ-d@7!~>?{mtWXaFc82YFn;*)JNl8q zk(8Q2OIB^5;LUsfcu;hmcwFqf3YYS%_K72x-bpks_!OOD(l};$I@vQ2B(C5aZ@R4V zel{~sgDTpZtf?>$f?Fmad!&8HMl_lR;Kf@=IbKs>Ox zpQT1L?DOb34W`=9TkxD+Ohdr#9lUmTWm0stQ-k39~WMA4!5F=bYK z;tkWGf;RA@A@CY41L(OIU!}i1SBeQu9 zUAj=f;`wyy)F}!H38j8)HX1c;!W^Or4Hz^)GOANkkBH5OX91g!C?!0O#6;9|9ulsB zkhG_#r?{(&7cZ8)2$%+hvB52xzxOVE`Q?}FrNmKUaxBf5KAk$W?I_^+psUT*L_o^1 zPbzg@Q^=}bfuYC75(^NlR5{MEvR*~|$pB|?2ZxsLp1ivcH@Dpo(G|pol*{Xm#=8#kc%Ngj1gp>uKxmcp5l6Rk@`sC7JPo%v}qK?&*S<3Y}>Y7%+vmZv64>_Fn>06 z9l6iQSW@P(>DV(y4ueX7@rf)nma(l-$}$58YR$qwvPgLqn^nS$p3YnCg5x%Ey z`YG}~E$p&kCVmm_01$|&_~l2@4tf9#-~aF}ef#aVlyNGDwZsP6vMctF)e>vNH%p29 zGIqnTR4o-;Qt%rmGvC?QRzhY=oVEGoZ-AKc`QB3!>60%<(?6;@(MxrDlULxtLNJFqj{J;u`M}ts$EdzkSayULCNwutD zS}(j}dM%oKU%UH200E5vbD;sDO~sEt{!|GJ-+ucYRg_my_?Er2l(oc>^gpOFJw4+D zO_;ur0kMcqo;pt1X9_4L`3y~1d6ZfXO;a_SJrYenS=?0LL^E>Pg30Fel_x0fNGA3C zY&^Z%_*1IhcD+)!20;~oF`(SOI7w}n-j#ZekJp#edsFje7V7WAdzOa9u_wSTC<{+K z2uI~Xg!0UtHE$Nx^YUWi=O{KF=MjLy%*R5O<`WP+xCXozgvzxSqPYfMht@zuvOb#* z2glmvS@|lPDJS;~oyj^wr?Yqltxuy#E7ItjWyfe*PzKEnPNTV@Cn;oC zCWY@gMa#El(AX76sX?zuF)gYRT*WrjO;u{w^P5xDG3cIDd39Y^D3xEx=&m>Xq?i*2 zWBI)Prw6HZ%T_|};8h6uW0DyXvVo?vjfVyh0UCr6fB+#xAj?W3_2L%lGpxi@515T1 zLxxb@`gO_C!O?VI{rvptozM44wi5Ug0Q>f|Jo4U9B-u@pFNuVh$YNVOA+qc@L!XCs z0D)9_lO@z~)m?G#0R&|(;A%E!PXe5+?V$w@qKQQ>5clhq7@5H0{@u%@8HI*omWRgwrgBnJN7sS!NcRV#3n?;?1RBeZp0%AzvPl;5Cp-d3x8;#E~%?7^P zg$ZVlUIWCdXx+XQ^M<)}?8I^QI*!xAfcezELt7Ct)*(P3k$wjf3A2Iaa3sXQ9Dr9K z2NQt#_~VZS2yNT8l{f{my^kM1$`fKLwQk*xn!WoD4eURFdQFZ|)$o35xxT?SnUYP7 z;u^_n3Rjg@nnP&M!RkpU0%EEg%vhR~<%jRN$fy3;H*+VCeAE&*0_ewls=&&JlFfoCSrXOYhdq1V8 zr^|W;f>!`dW@aWGK73f-kH=X501)7&B0C!%3Gz6xc-7szE5ANo3WJl9;^<)90ZPv} zM)mr|P|fZsYMqBQAKb&Ptm>ieyGPiBt+S_XLum@hpf<9qC5sxoBSIBQH=CNPf_{ER zN@&HP!$4WQF_YfxnP`$g2+wUmI(ZI1 zO>a*qp!XJDqYi77Hb4a!s=H7DCSV9w)n6S@Ij+rx6!jEKEh%1WIw@Z*$s6Htn301? zS$vICr~!KoAbrlxwW(o~#u7_FE(O*oG;e@Oz&ZrD0R)a%0>a&R9j{?M1UGijph1!$ zrA&(pHE!I5wnRnIp1r%MrT0jQIbhV5x|L+fRp_!oRbrXtc!t2OM>DlPvcdq4%7*I7 zpa7uo*}7kyFkNj#bYHJOke+?^Z}j9-f0I?;H>y>m)xklm9oV}tfB@k?su?tg&_zY4 zH@S2FoX9d#qS&Nt}oE9*kG1nPGGoWrlz`#Jr%t579wsc_m z@aw~BMb1Zg9`0XfSjzbdWyYh@OJ@DLd*WJ3^;d9-p(%<@FhE=A0%55J51^rB#WrP?0HWX1Rm${=#bm&3mE;%y z1QYl#RjWnMJpUX$_0-=55PyH_DOvWvf4`VD#X|vu)(loK;CHBFg_w-Hh4<;s-CK0+ z+D%#$x|L1Ge=~0aEqlgKTR@w)>@>2URXLpkM3x-SWHG@!lPTN+_BJ~&m!e`aRj^7* z*i?~9)5&?P3GN$Zd=Jd(E)?=~(gJ6#05hRm4QMT)NTxam&GPotOSb+Aez9U_yYw6< z>kW`o)9^S@XwxF4dZ@QRpAFV9jYsAfy&@7t1J(Rs z2EF{+%kS!oif6i~3* za~Y5-T0ttoQOy;CDsoi`Eb5N|!@sEpR)^i+p=#CMpjTdg znO=}A@;5|VAj7+cogMR6>r95n+Q*Al!|cg(xJ5B>;mp3up~gg5$>FHLQU^Q*`RsjR|KIUB7de`p-RO z^mRHU|GU}b0%@NF;lkwvI1pU2R&{$DCc+Aat{V*SpxX{K34;k?`kF@mDa>uhkqI<$ z;uvbspdq=}twS9;bmZ|dIk`D8AfBLSpL?1Heffn+Ag!jN%xF!Z>rcTUP@9S-DEMtx zcx>LbmsYOd{GT;l4GP^P-Cy?~j8~;}5_`xNtpE)HKmY&;PG#q*noAVZpszzN`}E6r z23Bi2)Vz7ptCErbKC4$01dB#kTP_--onZ<-HUzHY5YP|+O=kgv>OCRdYeI1>r1~SX z#bc2)JXWvoeGw=B|H_q%l#m!tLm32JI(Lz5C@g@X#19o;h*cmuiL7a?O`zrzfW~WB zyFl1_AZ(palxESiyf2c}O@i7vIeN(92%DYCRwLw$Y9*bUea0`GJLQ^OsiIXjh=q)S>Y4N8AaWx zl|)(rfun9)0HEK#eTO}bn{@H&MM^%L!GPF82NP2NYb}wRe|Fl$*?}}`PN0|x00K7# z=0ckeU7jzR0d@VG6is0W zT5ExiEt*1sqsYc14ATLSw48TcNULtohalI)MbQ)-7D^p?Ce`usBxiSL$&>u*tFLJ1 z&RvrB)~wlE5~0MvQuu@k6QuA5u?MVgz;qyZ1+#&5j-^XiP}??b$o+%CDsSp?T` z*h!_e7zF5!qkA~u2os>eq00E#goLR+4`L!VD9+J2?7qYunoYkTAW*Jm9NBqCO8^Wj zv5Nv1$u%}=)R?Nip-K}`0|GY`^{7~nv1$k13D4RHO=}2nh+8*rNqYp;xFD4MZ^PNU z_UxxgY%W5=HX9Y!HbSYukYfPF=-`6b1ZpS>RPikql3siLWl?L-)%rk%sf`&0)&AbB zE7S(vX4WeWp}mPt7Vp9|6GnGC+;}0J8x*;O$I&_D0W}(%Ep?(gx5BG$Jk4RURkuMs zaX;ZQf(Ib|URQeSEGX@UBF+BTv164ou5iS230)5xO7$DmC8thdwnU*GNz|N$C_HCF zxjEa#bZjU!M|XoTYT_vG*`QhiD2{~wTt(uEsY#>AWUc1kNa!6N4on$Lo}FE7dbR4y zQf>fqp=(u<1&(-%27_u*P--4^UkfoA>}A|!Kp@_7?&1a7zUv^Z3XWp!U-0`)-N73s zGMPkFOPPXPvq=YlpfrO%XKU#rb(iPzB>?o)Gf$hxpOJ%Qf%ECh zF9(yogPkPOz;(lG& zx*9{7k1}cQ(be!Iz#rsy8k(iW{A*I6xqh^D@(5*Q!)`lB)deNpY9nYUN{=^y%gn2rx-6s&%>zkpe^|?O^Z- zX=ezM8K$*`ifjt;WG>NUVvbr9F9u7O{-xtqn$J8QQAI1_mSS3=n8Q01OB? z!AuBO*kFLi_+4n+)_6jmktL>51zkEWVC_&#G*p)^o!Hdv6s?N{VQ2#sBBS^SH6q{= zC}0Md5qNqO437drX^5Kwh>MrbOa1Jsu&uN@v5r}`o2Xijl%vq=+x?L^6=wi_taxNTvL1`2m zg@p34{hC5@?31Kcef^WEcF#jJeaTk(X4FUuTpCC_w(p=-eEs+hNcqERExaN`Tbng& zCe>*$8#qFnSxKY@f(C;`D%tJSjZ>f@Fp;Bn#fsTDUtIjcZve4j(>5^|*fs!wkk){f zE^xY~kM886`Zk=U^XJY}{)O{WGl7U27GjW`f*_D*!v^G4|1EOz*)N1lB5`~JnvBV& zj=>MaY)FXOFdLmMUPfo@(OBn@*U`cVF$(YyJ~kbbV+iYzm?lrZgA^7KK~dWyB^#>K z#~p-}wfg8oCYVEL$m^w6ig_nfKO(vWbkENDT>fq|XO9Y>ik|Jv=!-fr~ zHmzGr>L0@Cvw6ZHzJdlQ&>;U{bD>)tpg7su?#SApT>;|02?+GsI)CA;@WX@2X{;f( zQ0mdgw3wbBxLOG1sjO^q9~Gg@HA$rghpo>OkMpXXa9l!y*towinSAk;SIDzL9kO$9 zqSsz~MFJ|d-yLEui=(K=p4EJ-#dl3Ws77U#!`3D^3=l|DRB=63WK&i}Lkg+&vK!>s z%LtkKt4gyT!&lOx#q%X}4fU$a`jAl#!GpPjRO*^dyoOi>RzwlJf=R(^b}c3=b?&c{ zixE$e>j~3R0OrY4CQ5t+ni$PX00{6kTtBkHbYnCO-7rn{&AL|^5a-W}e2<+tMM0rkf16^* zU*<7m_EMU=XtiqnSD<<_q*6|VUj5X>QoElTEIK~XUbIBMs&48L zD>vDt$37Z4VuWxAN!@4RR_E(N^31274ixo^0$+eZ4?IVmCvLtj2(HmB#%MIE3T57% zd%+aC@ESuiD6^p&z;`j4z>8*xuGl#eor{=mp2>)m3>ts;wHg{mK@- z^ikQwE#_WVp=`8AUSDi1aw&nMt>L2pF@X|n;~!WHX|?>8v`3buaiiaa_g8HHc{bIo zVW+CQYgQLw`}OQWJ$v~}U8s!LU!_-GtI9yGE;bu$AywaejcRyyHkz2IWMS9-X~wmc znd>WEjmGYs4L+g4VKsXlpe=&S6o5lj{H2kxZlUu@9b3+lMLATI!`=P-^ML{c9dgIL z#PU8!FybTtfW#!8ep>E1ybipsS2i^mGAiP8WCAyh+J1A$Y?K8z z4oy)Jq*DDX3yr05<%&vt!aB^wt`dt`DKk^;8jmkf_SpZh*!y~)#PW?DEGo8ot?IHS z(Y}2r8ar;Zl;n0@v z006uoRGXo70k{vA=b9yJoyly;x%Q_4AhYe&2jELi#%_U$&C=?AcDUSMO8> zII{o4LD3eCXIxS)C~E}Vw05CN*zJw*^`k?FwN;~aBX@$2t(M)V+P&h;h#xe?fYCuT z^y{J2ty_2M)2AO_&k!2?^$=0XUk({UJ$m|4r;eTI^TA)z2=?~}^zTnYh7F_727f`0 zKDL@od}pgg*M$t~M(%iw9RYA1)?wum9~(h6b=@i$r<;c9tn{Y+Vx(ExhK&&vdvHHR zZVspI>|t!)x^FlE+aV_%B1Mhie2AT$tc&BaysHvj^&4eARhg=*Fv+Tb3+)kBfX zrY)Oj$nYWb!MpEMeeb2F8z)*~;8AIEs`DbG^>Ik4nLYIzZDApvculrl2)Qp_OXKmU zRfl<_D9F`2f(8v9$Txf{jT$vtJPvm^cXIJ?p^rcAOk?@laf3hq;xq9$a8nyMYf2sZ zOfq*2f}M96kfy-E9)jjN^8X(L2dH7tG1$3t3k~^l zFg4=|1+NE%LuqMglCcH180Qc>L5u{cfJgvFYa{f=0J((5!22{9bT@yk88B>sI4_eN z+C4Qroz{kJqfOS;&zS)$Xl~#tvx&Icm*T8xA}V)`Rbapo`G~l&a5bNJ;z_n;&(n)9 zy&!Q2++06jUuhEh$)}%4lB$!V3)QaMOwC{;iN*;z6O+yhAS7oZM72!TnNHab7%x&#a`g&S0K^}T>AW`eHTG$o$;eKC|hi)8Zl zW_OY~4)_A1sGfB_W#twn1e%lS;2E?qGQ0o~D~~|yB#=le7_5N6Y9|)@tbjOr{5Y-K zu$|U0C$>3R-;!=>M06|7pP^Ck*yvkF8kq||J(ZVhDVbBe{^ z7jsj8RF-l-ebqvgQ^z3c>ED+=YWY6B%IX!P8oIu)Cc_PdZ;$J($}Td%fR+Rf-DAv7 zH#NLdsP&TTCIC8x7OCBYES^IpZlm){Yfb$zRSt69{=ual(owQtvs zU3GhMcCk0>O|S-ofFHag00L1-xWsUuQG^693V?uyfX4wh+X@7$slY&cXG~&DY=ja{ zpU#p9b6Dga8?iicG=pZ$TTUUHwwi#j@&)ULB)W5~2E*~=Cq(cXp=kaE9~tZ&v#uAj z`BiIz1i9|+PUOt28G!I=_%=C9#q=SguXd8;1gOU9g{J3W1A+w*p|+b372V$0yhWmz zArzeOnMAz?3=xn-Oz_E#AJZUYp>&tI-SfkIq9)A=(w@{ zg9<2FHI)KuaV1V;z1DWdVw?bCb+PoV)bSXk$hp?NAoqv0APU@04M+itEtet5vo*x^THvJ8w)^0ZjX^Lwg3W= z$(aGmXzQM6i-tHa?EoJokdJOivTxshs`kcf{6&9}qq=AZMmZLa+R@B8vn4Zn^@>&0 zx9=y^yv5tpqE#yzKKv^hJS$oymW)yv^SDwY$UW)wsg>YRH;T?Nz}9dAR04a3^VjksAr!~ zgi!YC+mG6|{*cCu9YrHYjv?=E{^SHt1)l+jKo5+iw;v(4Wrp@De(ca77W22ZRCWVs z%h%`m^=Soue`PNGM{lOXsmT&h8b5xL6fI-r756PFY752e-zVk*H6l0 zgb+3eCbR`K8vp?rAQKF$nzwG?m0b0vE;$+U* zn^m^%jG^glGUDSC84#B%?Pzz_AeMLxje#BOE?m}~=C8_{004oDfh|K23UPPzW5RlX ztE-!647f*FG{Q_k4{lM!ot6HsB+boFS*Q)>&G(|f@Rm&`7 z6QOyA2qLV^NWCkgI$s?%3xuSS?Crty!TTT3_;FLjGxBO!mv1CE#cQl;-=r>GKc`s4BwdN<&mO6KYo>L$hI93HG4gUvk?dx!AkZ)i;&) zBpi`+0o@eU%c}uRnmkUla&T~nbgR+%p3n*~A1Ew>cY&}wIFN444pRXcz|+8b3;=Qc z`VHB8ssjaTzsSR4&IROG>Em;$k_kBLi{N|s`Oqt`Rg;u7%qsCN_}F&XE~BPIHC%NaRX|Ob zl*|8Zw5*gGt|*i1Xw3ho+2V5bn!X-=eU@u&yr_bIOBuP1DG*na27m#R5d)7Q1MoL!6o5hPPkPSe z3GgVeegVyor3s`$o;Yz*TwCmgzAk)+G?lFq623(MarEeM!<|$v396L#?TeO`w@sTO zr5YMv3}nWEDGmY%T2CIzfXj$R zW_6}srABC|&VWEe^~QYEAZfzq<+(8$GB7Xz5P+lM5(N?n!k)dCH;n)oVji^{cV|`G zje7X{NoH47$uD@7s#dEmYS*>5rA8II0nEHD|D)-mGWq|_7C%srS>TN&TYv&lVt*8-~L!J83{)+s0#8Q zrm@?3`~gijvdH);W3S6|62U@q3{(ki+_r%ZB*#*8{2n@-o-8QCKLiTlJxKNrUkm_& z3q+U|jle*FRCbcRs5q?UV|jP_jH%@A;mRI|v&8SQzTnk!qf{#CZZvLRWy*~N7@91u zpay{o3=J$dy-A=NT2nwPh_LuMW-g9yBl6ANfh0kv;~ME&-=}wP@s3`r&Ys09Rq2gd zRjH=e$3{=?L(-_->C>asY-xo8834dDzWyQwHfSP!4o3~j%A=g$Urt`rZ<$d^0N>F& zh88bhP0N<8loSC}oI&8OZqDL1f=eLX4~tkhkEL#y6=Y7~{^33FG!W;(nuc!D3K<}j zjr9)1lCX>(9vMy>HiuD6QZ((3+eHZ}2_jn%N@UPyWE_{$#+cYR3f{Pj4kV^3KtMxS z0RghHWA`rFx^EjDK9xjqCt_(=;#P`D-b+_+s%?s{U%M&f5zDZ+7#x9KB$^=02S*Sd z505(HGw<26N7m}|@^fg))JY7Ox2OsG(_fDmP7!-EWuGsVsjYe{c}}`!Y{7u-7nGL3 z5i_xo92G!tuKuF3N?Jp-2@A_>#tpLoS-X4F16N51*vG%8>UwKeotiamO0B=xCcPfS ze4*3)h_kZ&Ln8xhN&{3d2rCp&4Nax5rIC4Uw$Wfw5xEV|Gt8EXPIef&MfM5DPJR$D zyd6vsm|0|RAsr6t9c>pesStC3M{)Y}Y4I4q5kTIp-TJYPp%ZVx)nM8|L^p1Ypp=t| zl#m%u`;P3Pod>s5-Z{0^CF*iP2LOoZ{qbTlV$sSFfS5UdC9982(a zf)9+nyN{nfMR)GrU~gqL)$@-sXD4Qp`_L?Eu%Ji)A?nvSDj*mjFtiBHYXQ|?s5FPn zU>1t&msu(X~Ci;G-C893JPAQb_awz*yEs7sn_F~jagnV zP|bD)N~Mt+EG{>-K;=ys+{NCIUHw#Wnd^!4!J)StZ_kUGQ$jvh;s zmCESo7}2f)^XH2BhT4bl@E({8WO~8NfIA9MBX0s;T{X!?`HKJo;DHtwL9`J^Vy6NGI0OKZk#W-4`Bt&elczH&Hg!LR z>{vtd*3P9dvq#c`RSP6Es(oCfxZ@&#PS`rAF4$tA7wQfuM~(p!QUDm34rgZ<`skz9 z?0yDQM*1=8?A@I_++4`6VS9;OI{F#A-TEIUw~1Gj&=-`7pc@(k{J=UhA%KQ~h3Y68 zqD%>lj~?SLn4w|;hIh0q%Y(!C`1{d9cICX@?qcp@EQzlDPEh0d3Q$c9Qz4osut@#~ z_>CGRztIv6&Ff@OXTlZLeXqOf@marrEY+{qgxp-1AGkV`XWe@2TF#bL$FIL0Dv?Lk z-NsGg4p<6@W`)po{|enI32A|7mIkw-;}9?z00|~GN+*&s5-EI7C@lVBP5~f8I)2`hr zV{>yQJcmKY)y_P8gX=9|;b5;00Y@>9GV?r+dNk0cgw?g!e17iGFWqclf(rE-9-Zjb znpNqoMh&GY2)f|e8T}scf8psg2&@b`+jo~$`hWQU8U$W?*P;39HP<0o3W)w{Q?}Lv z)=R5H)SwEXW&y)gfbgM(qO~v?kD(2a-wBhT^CG|>U?!lQv4jsIuX9mADq*S-bC8Yi zFJGcPu{&wXya_aE&O|zLJdG}0y&~xi*!Ug`TS}`JrlB>TAmt@EChuwr#2}z)%8_U40B8G%y6BkB{1NoCCR3+dHXM z)*3D6GHBnF1e(b+rcv##QD&E3csq3`U6%i4`;KB60Agh=V7mqx0F3dt;k-hs-S>!U z=j@v-UHkfeIaPkI^gM<`fEtOt1!I1eyjfUEWI-`@;fYd~N^!n9P{ z&G^O@x^@dg$rGjsCL7BRhuNIN6WO&lnnGAZ965HHs%+bPKmdW>$ST&Yz6@~&z2PZ@ zk5VuI;Wof<^CmyPA+sMB0sEy{uhtN_aBv1J+@Qipca+yv*sB@+NkZjG@vqXtX zy12VlYN-r!iV!k#9AFOgJwoLcnzAF1hrpDs7r|%2(O?>&RbVDGAfTmD$gDTAy<}{4 ztz{}s!`X9`&E^C_!o!DCh1+f49ZjK|cGHQ|c~m9lV1fYRKzx!JUr^fNy1DVG-u(2& z4Ym2{&0E(c&mTz}I&2EY4zB{N7%B}Z?x?^uM!g=w&$htI)vx)*$H#6 zOK_DApDv*>6DLro0gD7AvN0;FcIPj0lzGsC{*CY--CxYucPya9+=C38*13O`ZDxZ* zGxePsBXOLhq-0scK!z3sE~G9xTIxvw7-$T*nBZOz7J6%9062*L!mY%*2i^lM0pMt} z4OxJ9fCuUU@{WDbCGvdstdSUVMy@3#<*;}*TX!lzoXI~ITqQXzo#riCLpx*Q=<>Cz z#zM$-Lqn+WCqkhBgI-(LX<4{Xz1j)46IuW%UN9x#7YI_pZ^nfK5V(i~2M!2W@LI=q z?IopcFSF*8Cyz=Z4H|*f?Y!8u`LMl?gEHi1*9%al1N(b5oLlx7FjNLeJws^toZG1L zMsFzW@0CjKzER}W$b+0atfA^ilQTAMcOP?6-v6jc5&;0JecaEljGMma|6EwCVtKgx?2n0(eo|_le24c=5VNm6MrS6>|gE z(x&Zu>B{wMbi)9_RaqswVS+&~rRw!|Wbz`x7R$)E7`UF`5Gb7kD6C7iP=z2*_`xtU z&>|pKuBfhR;6>lCH-e~{x3`a!zuVVoVm2L-8O=Af&bX_5vx{WEFK7u22+1}IA9-G^ z2O)Am$SH0TE!h=;)XS69M5uJ7AJwNdUQ^y4?{xG=3fptzYsGDNx>gfkny|; z2E9!-%moM~01+P-FENb`n|Ip)Avu+c*Hhq%U;zP0qh#0Iw1Gl<79f^-v-Eq$=INOE zI%@}jfMx*MK}cF}Y6d_cB8M9R8>p+BQK1b@0YD@tC&-ouNT9KIwj=wxEsaj|31$I~ z`?xFSjhC5e2tp4$2Vh`Qw4eY4Jg+yeoa&6fXzuEx`!VRHZfK%9<1UDhJ^8)ZeGq^E zs32tX`wWvM+frKpKmO-jbh|a z0M-l*0#%6{ftn7~FXD#)ESLeh)2yf8Ml+x!0i(g$VyDGcW6#jJ1^{qm0YV_2^VFWA zIAWhsyryR^z~TI5wu%e*ssdY4>HOSj$Qdz1qIu>RLJuf1M)6~Z0FXyR>{>VrpDQEh zv6svhR+u7>K6}(298UHUl#_Hm200K+iFii&z#L~_^`zUPl4%!i&U;{)1p9o+r zaq{#Tx^eTG>1OJ@Jn#jSgWWZ>g3kR%l@Q2|UVeq^3AKj^8q)Bg=8zwO3&s0@ez>7v z*GOHPGiabK@5c9F$YX43 zi~lp{zJS7Qh|1}dMkWlpe$x*!U)U_YCISNHONU&LMkKso>n4PtQE-grsUUc`AMg~A zdJirEf)37s^&xcoM{*2EI_@)wrC#ZT3_v=yX3&7p^)vtkqL*-Sv7CVS?%#iaw(Z!< z8e%6U9I-SZI}o2DfItPfjW6hA%{wL_bc(kw2mv4v)zk?ZP+>Sa3$^Y%rC~4x0N8=h@?F-U|DXDw_vN_gH{Gm_zKP%c(xAoT&+Y`GVpCclPc)I2hAUYsE004wfY5;{>pg;&fV&Q&4vwK~PSuvvtz;s?T)^dr zDbeYV+Dzyot325{BF9XYLGv|eBWP34p{kHmh!P2#~Vr>KiqB40jNu)(HXfWtb zXAnAUm`(==r+|$E!G!66kR^M{h{8dGAh3c9vJxk~FBWbD5=miqot*e{-F6szM;ww_ z=Q1o`00Dt(K-i8YGE&-I2GgpB?X1ifpL}T!5uQ$6g7{uHd0JIKl za$9$%+VvP5M;G`=F;a_3>`6JW0KH@rmao4aY&JvH;b|SZhK97>2fT(j1+)kzldedI zi2yf)c7U6&L)IXw0E9LZ8VuH^FIZj0Mlk>cf?>OM?WPS;dxTW}1`sRPhZD5K#VglX z8{Dr11`PylCUjE@-H!kXn?Nqm3iYM8U&i7K$Rsp~wOtQ>AToPmV)lz2bab-aBocKDM70p@@J=EZU<)UWcIZ9@AvZRj6`N|BLUbJL?`fd~)1OvccMjQ^W3(0Mod66FLwb zL*ph+RzhblOYhqO6AJSQZK_u^bzA~T$>12Oid}7Rk02C2i~FXFbZ}m$$UUkVbUO#D zyNUk?Q?+HA0>s{fk7+A}Nag$`>j)dB+`U_9dJ_r|g)#sJZ6;Jx%o4Me4StX|8vuk} zxPjmicSpbqb`GIdxKJQZ$d|xtNZCiq9qcDEs$k=gO4fhSXVjo+6Y^@>lw6Gcr_??Y z2gzgPCE0%*0#_!XSOkl6byx!kPyiSRk&h6X+e`%@cL>`6gMJV8FxQ_`AS+fNGe@E2 zH3JZq?{=Sf%?L!PF7}Q-2dGZHM%1Q#Me}F<^2{A$4=+c{G}nZZTB9!bFaiwGtk4XgB1)g8;GL8H`XhkC_e*8K#%|m ztimB4uZvglex2+AHw!lnM=)^k2e5Elc);A5G?Ue4x3LF}9@oj@8901?!UBT(HV_!v zqRvdEK`=ZFAb8GDLYEnBzE`~;TUc9#{$CFT5(Pd6#>^se8F5|(qKwR}w!?PwZ<@%z zX^kxN2Qr!59JNVO6On^~djii2-UIFpW-NX)Oax2?Uc(XQSnmh~!DC|K-s*b|bAkJ) zf=|EI47x%K<{~XEoxPj{$(6-~i`>G1h}!x4tqB8{ucu`zBj_$`0_9c~RpJa*Goc$? z=|-7Y1JNW0=0ZBBvB!ak8tffhE2t{?(x^+sx(5baRA>vtJn+MGYhiq5)TnPL|2(?w zXVX{TOj9ufpH$WUmuI2t((|M-OP|w|G+%p03yJOltwU_zy-+OP7 z4Ef$^_vNUc(r?$f>pZ;`J1+pn-s)`y=Y^>o5g6=@v)0p+GQ* z5Y!xQ0AdV!ZC^*@kfjZxgD|-EICSFa^5v^&!GeY4=2?gA+pU%~xLU>zJqR*k_KQ%a z-W6~_I9kZ+@&9fB2yWBwn}WB3LxawJ${niJ`-s|BvS++_80~!qP+EGb*-YIUqJ~D$ zi7(c@zTjCvGa#^sbGnujF$RDFi(TLlx^oQ3J0@CX5}8}6eI&Sp&W=hxVP z%PtC!+DCB-M}Hp>htrSKf@Q(9cmJVEoy>H1Gc?kE)Ku77@t2Fcs55|Z(Qt>LEuba9 z5kN4p{H-gT^%1$4@V61I)8}xb+}vGg#j+rpw_rZi^>ibLCOxFNr=8I**`?1ha+`LG zTxS?Un##hPdXEKoSB^OMpAPvPJ~PEO@O_WI#{|h#4TgK%bgf?lPk=dv3#yBIHJQY!G2Bn-^v9Y39E!jYt9rl{=-PzcLA|B0L#?~)WMX%#nxcZA!-DRKqz4sALe>(Q%sc@E-DV$PfQHb3z>uBa zjHcVVGdpIwRZBoaz&wB}fFxlcQAVej<1sh{mTgh#3{L~512c+^a2?Vy36cXh$09$0nLt8hR!W%tPSU4hRW9Hg~cki+0 z;P;00{U#8m-TTdV>F@KHbfePVqpp2osUYuyTt7Ss9Fdp;VS`k|jR$!~Gj@0e_|3?a z!WsiiE|Q0EUm!SCeZ#~;>mtYp)2p=u!q=*!aDize^o|7@4BFL9Oi7W*BnbWHt=nnS z=3Nr5er&_i$Neo`9Y%o+iW|4@QlW)N>YmD4GiWoR_iWIcfdP$LOTc76E$W<0oQEd? zK)|jcLkeaCY7-^`YaU1jMXde9)*s5AnaIk1=bd-iP1+*qd(HdrRm;l8sv^jx0t2+b zZ6(Ob|FeP5Vz^8-j+5`0z_4l={n+X2Ttz00rEdQj88m9dP%~5y69M7}j|0RRlS7+C zXbhM{q%ES-8=3;z6hsm!1X##IsRO=C$9Qz5Jr=-ptiihDkrfa&?T{!nAL8b2-Yy9- z`wk@j=R4{|$0pH2c0c0|rBJb@!@Bk;)b1_cR?-f7%O4F2#2j?*DcC)zIuIhD9N<9g z9VS9IB7Zb=4UYv0B~lcOBfo||4!fgwQ{xUJ&Bk4_@YU-W3-GqgWcP`;l)(6CH3cH< zNvu64+6JCKZU6)r&XX#G3!f2gVSF#ll;dY7Rf4Y3zIoK5IF)Me;$YTn!qb2-zzwWP zFZjKPEuj7quBiqCv?}fq%mz#+?%!Yk`d72|0?Pr~z0{_{y5kWv1L6)!J0y!{MIZ|I zH8P5|1Cz;P$Itxt_T5^%66A6d-MgnuM%hEf8y-|VkWE6Z+xyry68+BHWftlSKMp?x z$Ogjk!;tm`k_pcO3tW1QL%X4RQ3r%cfM5x0`|=Iivu7`Bm^NhR9b@e46-zaG9wx_O z1xj!eZi=v6CLwxw&lv29Ov1Qlj9WJ0PrO}esPpQ53PiUA943IKD6qLrDiXjr_e@oL zWc5(_nsD8b_=7|r0R&$^00E&x{ad{X{9deHA|Ry~t2B|sJ;M41yfdAE1kVCs!OXX6 z2fZPl-VY6KCQ=epj-=ATgo6@@+P0N>!=|mw9rpcaWb!wAXRzxDvypt{xXB-|pR_g^ z&<+|9dgwiwv8UrvTTm%_h}~=ri`uu`J$( zeRBJcrV1F)%K@2BPM@72r^!miL$FGiO0YJ8-!;Z<%kk0I9v!#kJ2W5^H~^A+dH}EQ`e*i*iP5ItPivk7&ObRB7)($w2 ztSM_~S}$D5KB`$+LP}N6L%M{iqYvzt4P+uCx3G5DA)CV|rJwwt?cKR(Wf-jvj--1` zES0%nkK*A2)6LXd1Zq>EcdEDTSpTCCBd9su*i;8ua2}C4m<`16!Ke|C0k42MMC1}_ z{xBifJ995iMFBqW=TZ;gDsGuri{*2vsB6 z2(1BPsS{S<0brpE+5_DX9YK=JT_xdR-A-dR>_2Mq*h2@Ko_pj=1S zpano4p&77H0}vns8QH(k42V-eOTf0m8@X&0AaC6kCE;AyRJ7nZ&NmswFLp)-H3Z@` z)rpm=X_@u4g`}L9051T(g%b>Vot&JM4fJb4iH2>#ClKp^xrOg* z>b{OU!cBaadB|`7@OuFP*gF6b9OzFE{@_7j%V;zrY4sS;vZ$1T*Y206IB-*+fI@(Q z!(~9|A*)oF4glx(eed_0*BkofcZ$Sd$uV#30lP1j@Q9xzO7e>-Tn?5T5Im`xH0m}03d2ns7a28K<|@QV}VZ@$f4cB3gOHkn+B zIpp!~`Q(7W!T|CA-4advdk)(p0hLfHAh0h523*gdKQ9}O8tsd%pa8#sR6v{qPYZ4k zKmmeM-etB84*A($0hoYmMYHjiTGM#_|LILJk0AHZ{0;bikNhrx1-}>I@L%k)z>qIavK^7h(v9XBwkjZ|5&A}` z8Dtr5Ymi6q3M2->9LIx!rym5`gt_O~MZ35sFTAkgBRP>y0;x$aP!q^?FjhqYrDbL^ z2;3CS7Fu{L-#d2>6&8ER?@F)Eo}O>L%W4DD<@<-&3>`Bb%ZUjF#OdPLqo z=Ov^B#ChPxemO)O9-eA_`UBVZ%9gLK!apC@ZUJOuOf0#QGAJfK^~!@mS61OpdVgC2C1&K&$oO&I42t7ptS-)q+L)X? zPv<7j(D@4h#f2#nLc#Fihabv@D1?dSR3Er0usYzhLNW+Mt#(-h&p@OQF%G2VAw~e5 zJ#StR-T&wYGu_TA_YYXUho9twa-hNM4;xXh001b~`P2noUuqlGVZh?Q!2kwVNQ{7$ zO_p>pv$_NS`8Q$?zx~eth}cHt5{C>Gp^Zn81}B;1)2gmC;RT-`Un7tO>F0}2G)(a| zH~|64fGTc)2a(UD)O1l55fPCT?M|iGgj}kqs{Ql;A=CTf(&*i-vE-?&rP1S~;;cek zd60aqSdi+B=MeGNy@3qA}4m5C`4+Q?}ecJ}Yw2hw+*x=(902s_$ z8xV-8+`m}JA`U!>rI(3G%&`eFzyYZT&^RaIAYTNZSqUVhhguUlUi(t!B{o!rA(80u zps|X0RBJenI)C3kF@_5*Q|q-q_>gCzwwhGp_41Cv8FrDWQ@;B%bi#_5Jn} zE`WgA;KL4Bdx++)J0w@^Kx+dC!M5}`EP#>kTaqJiNtqpKg{Ly;TR)JZWq2i_yA=!o zF#rvKz(ox|1JolNP3n$@WWdir#TaYC0K#caI02z?3Z%qoN_}cZhQvzXuZf6>rx;ch zQCGs}@NpNsT~Hkn(aF>|Fkna~TOB7)o)Y!pQyWG~IDs%75ZC|>dQm}L;AY{80T>`5 zz%w99;ki?99&!OB-HxRM2EQ*_zLZ}2W16Y#*6~Hls%&l$xNd-7AG8ji4|iRUeZU{t z4q&L{00;zJc%OfdkXXB`eYT8LM0p+tu*Ne1UbJu#-TUot%0X+u4rVAU415+HX8;um z(10KL@)}H%%XD9ZstJGrQB2bgsF>1GUy;O;Au@si5hV^NS5h`LwRXMc_vc(W1v}}3 z&^Us7`{>xHWK?N_3{23;^JfJNdf47K(P~hM}h#1`B+2{U^ zp8xmf=*dNkM9jYa#w)bxPrw74Cp>SA46uA=8WcJ0*@;&7DS*!?m7X4qSi!uv5!X?JWj?#&V zV*-kEXV2LjVmf!2E-joq1IZ#Fn;?@aRv{&zGK7rXc8kp8KoaYwjhkrY>Xr1!!;jGX z`S+6lBX3*nkxiqHxvQEeXzdWIii6g{@`3WCHD^5m6H+ACn-MND7t`qB_LN zxOiDWIKiM!EL@RR2K(H3Ga)gcQfAJ)QN|)Y{`jLZP8t)0G3MZ}|Mp+)8c^wV`AoG< z4)0k9K=jBC2pMG4v1f{UzzzuM^}U8f2cMDg+|M53Z70^$Y{0BYu zlgH?5cYKXz-7!lB+TL{2t@8IkDmb|UR3Jzu!v51ICmSMZz+n3s_U@H%Hin`=GJrD_ zmUyHm7d(-O^Mr-%ph#DufFUux;IjpTE~pOpCn~D<(%ATjm1}uI99Hm62*JEKd0EMT zt$ag40dk5~10bBxv+A<|zranNF=Hlumrc*R=G;ZM-Eu3zG$Ty>}8X?pY$(gBhIV1Q(hWEXd$v`v6T0TLOT zoW~|+=G6fPU6?YD!Qy+G8iZsX6HZ|~nebwQQ%nbeN(SdvP}tTAzlL27lMdooyVZz8 z3w0l}ZloD3HEv`x?&h0rrn?>v^+h1jfASa2c~ z3_uPEC=8kG6%`|2!yoa>Zb^obQhyW-JsK%(kOJrVi`4q^SFWcUgfOxxd7a5&fa*h; z0W!Uu71>iWr5iuucoMg?#TiQBg|sTR5k7~nVf*$_+7X3tLN1$_*;f}Bup0KYz4bwu z+l=a|Yci?(W5Z&7Xs*O`H}<7~pwdA%2&!HoK9R5rv5TkfdZ>~wF*t5uk^I%`<>|ch z{%5Twr1>%re9kkq#&irZP9}iBHX+&i5Yh?tz$yW11y@xaB0bg{(-ZH{S=nS-4gS2u zblHFCRsLK4ib?Qo^JLX&Kq z0W`cuo&m%!tdFmM{Z8Zd{j#4tnP0ub-%=YzlGcV2yP!2J`q%S;vjhlQqddWBWmpcV zkVDosKLZINjw}9Je#dh)w#oq5ZVvhptArZ_3^QhaMR)|pEg%UN6;;koF3z#pkO=B) z@ByMuJ{J;d)XxCZQaioCZI2AH?K>g}Eudgc#3p55y9Tb670BACW*Mo=O@* z>wuAA$;kvLV1=AIJ;4V(H9USPFgT;A3JPaJ?~&0FN={0q<;#}S-LsiX+kM}QAk=RGf5z;kUNL9I!g$g{ zv+lf?Zolnzy7TUD(9%WA#4*&`)LlLJ!-AB+#MtcoQmH1_Dsq#od)&^@cIHnwU*oDtH=4NXO!J2m zOmjOYPMnf9%v-l@rl*%Lr`bPz-R?B!Z^bw4*;{zMtel_rIyOr?Dd1NJj6|?}6af~| zG#<+Vd2OV~0ejMKfYt1D;gZGl-g_U&Q{CB#ndu!e=F-{y4O`WOvqXP7XE5Z^QCDPXLBuYsyr2PjE(!k(hX)%C`u#sa&Y)97g zj4S6=zvq+;P(6?~6D(~;C&ui8q4BZPG(Iv)$)yL(+)V&raj^{q@gL|+Z*UAP_Q8|? zY%Te(XraK>2Slw1x#VlGr9%7}Ji*q?EJ&V5U)o7sUG35+w6mj=_O-XmZnL_-HMh2Z z#F}vW8|vyBr^F>-NjS5e5VZstU`d39MM!fncp#^=5BxkXe2C4F$rQ=x#-zW#!@ZId zF?a+;#7AjNREctov*N#)I1Tl1#?Hi2so*RbR1lnC^A=%v0OQ#B39)Xv`bX&xQTyoU zFIQT4Y1ivtg6Zx0o=3Z24H~2uZV zDv%B~A#YVnJ!)%5ht*TM-R>CMWHk!Kkav7$?D{5CYKLJdhA;RWPKb~qd<_+Wkr9YX zz{en9h>8{!5u21tc|~QPZ!qXWKIYblWZE8?BD_NTW)DcqqCpxS8IuYzQ6-vmb9%xC z0J9b!)(9 zIp4)r)>VN$z{SKy_`0}UrtH8W70lKJT;uO2G+0eSJIugawIo{iNi8QvBu-C#GY+S{ zb^{Mc1#pF;!XoiJCZ(oQOq@{>nB57!kdTxkNiN>1n!gM%=<;~0X&VCq!@iQ!^Q3M6 zp`QIRd!q-VDMF+9~0k)sX-m3QEZkzs7oChF)fh>SzXBh z82*2_1*O%?Q=<)*nh03h`h3rnrQRiOYtM?CufjQPmIVwuPTwUb-cEG>kw z0SKpbaQYgQFE}%!VL`y0EGa1zu8@|N$xVAKzD?T+( z27X1k(g_VpFl|=HK4N+gqNjt>zUZhN^0-wG;#3m~gkw?`aKcoUjT!Yb!WPYuqeCni zv<=dr^t$M06@?~hLjz;d{;08~m8vSdl1mU8mq)K|E~5pn?V|5IZTerEOl~uFN#=H- z4e|ny4UpCjGY-4OY6Ym{2ZS%Q_)^~_E1FdVMjD}^+fJ_;OMtL7dQYJuJBF=@$jB(+ z3MjV&afGueue6-}z6c9_3AVCXx+Nx+^2s?EZiZzVD`dZxj7KYA-GNPY*ruVmY~U8$~*( z(+T9!?g!b}=qQ@mZ36-Ae2^ZW!lq^c2KT)X!) zO7rc|=p^Zxh`h~)=6x1ZZxPalt&;+^7q|A%#F&O*e)@-x3|bPwbk6HPI$*$n*Zi}6 zgA6Jru;@L3xz{l5a=nF=U71D6WeF6Xv6bR7Vq|7W_rXr;-rq^>2QY)IO{N6EztG;* z#X#sZql#LaEVFW-fWTB;*HC43jf~BPKS6bTdrud{xshLP% zRobwx<1N2y%Pi31U z`l-Kf*Z>D@n)`>OS2u>xVmc6>?DFc}lv$ES(OF^icEmgM${$~%tXg<)I!Lbj;C@j#W|*8A8HLvXQwRT>vfaDrcklk1*1jG>zj$diRn}I?&*S^Xuh8M} zFg9Ab3ak!lK@clN5_r9q=~z@O(g6GbfhZIzqm&Nm_b?;D5#VV=gL%Xtz!SH&RFj>R&VH^+~Jxz!Y@KcLxOLMb5MMlO2 zz?ICeJM4jErfWPTO>ILhWfx|N3P8JouJ%s;9j2vUy;V1ft=>fRUGR8V5|r$e!Waaf z(1Rg`L6De|BGN!-YQb`da>cP)$Pl#vCmqbm^4)dUfbdED7w)utX`=^VM8>62Qd%w* zm6TH@A5c|grNjU*Kf7{IrHF527}e~lu@19F0!Mr6_`27C2w!V9v*`zIBmlsq*-75Y z3aP$=7ZLT6MWrP&4;=u=&dH>V%rwbyNMUQi&DKH!^8*0^ON40n6x_+=O3jz#6$GMk z@;p>keGLd#Y@uUXk*88x@$RrTz>$!a!zN>qbZ$W+3CJAE;gM8>*SN}|mho$EnY@Ru zz0Cem*H9+cau(m^RJ^lTdNLsy1^pFp_^6eH8bDbd$_WvDOiY2v7*DSFH~|3K{Kdzy z6mw@#d}6k!1k^g8e7L2O zuAZM?B!MGjE5j*-otK{@hYkXWW+j=qnNm@no}M8amH|j1_yDq-MIFSurEwQJ!GZ@E zRgfz=jc_KxT7aMBW4HXfwyylDtKXN0vVd?`ibxIJm==Qu-vA0&ePU`3U$a={WKl{c zo0}QwGK4H8Et^vLeRpyyB_?Oc#w@CYI}t#RITWDi^~bDBM*=watzZ zMc3BVwQ3t$D$6Qsne2H)e*+wlCa7jY(=EKG9aZ#-vUvapSLgR21#swS#}l8zRz&_T z<|++;{z8~*>&h>TGHz}^@LWZ8J$d<1D|R=@HLGYR<*>Pn*JVun%4^JS>FQp9s`oF_ aJ^Fve`&$odQr(>Z0000 + + xcopy /E /D /Y "$(ProjectDir)\Website" "$(SolutionDir)\PhoneGap" +

                                                diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index f34c6ee4..bbf75f3a 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -721,16 +721,27 @@ function pagebeforeshowDiscover() { var address = window.localStorage.getItem("VocaluxeServerAddress"); if (address != null) { serverBaseAddress = ""; - var prom = request({ url: address + "isServerOnline" }, "Checking...").done(function () { + var prom = request({ + url: address + "isServerOnline", + timeout: 10000 + }, "Checking...").done(function () { serverBaseAddress = address; window.localStorage.setItem("VocaluxeServerAddress", address); $.mobile.changePage("#login", { transition: "none" }); + }).fail(function () { + if (typeof window.BarcodeScanner != "undefined") { + $('#discoverReadQr').show(); + } }); $(this).data('promise', prom); return; } + if (typeof window.BarcodeScanner != "undefined") { + $('#discoverReadQr').show(); + } } } else { + $('#discoverReadQr').hide(); $.mobile.changePage("#login", { transition: "none" }); } } @@ -915,8 +926,7 @@ function initDiscoverPageHandler() { $('#discoverServerAddress').keypress(keyPressed); - $('#discoverConnect').click(function () { - var address = $('#discoverServerAddress').prop("value"); + function handleAddress(address) { if (address != null && address != "") { if (address.indexOf("http") != 0) { address = "http://" + address; @@ -925,7 +935,10 @@ function initDiscoverPageHandler() { address = address + '/'; } serverBaseAddress = ""; - request({ url: address + "isServerOnline" }, "Checking...") + request({ + url: address + "isServerOnline", + timeout: 10000 + }, "Checking...") .done(function () { serverBaseAddress = address; window.localStorage.setItem("VocaluxeServerAddress", address); @@ -933,8 +946,31 @@ function initDiscoverPageHandler() { }) .fail(function () { $('#discoverServerAddress').prop("value", ""); + if (document.location.protocol == "file:" + && typeof window.BarcodeScanner != "undefined") { + $('#discoverReadQr').show(); + } }); } + } + + $('#discoverConnect').click(function () { + handleAddress($('#discoverServerAddress').prop("value")); + }); + + try { + window.BarcodeScanner = cordova.require("cordova/plugin/BarcodeScanner"); + } catch (e) { } + + $('#discoverReadQr').hide().click(function () { + window.BarcodeScanner.scan( + function (result) { + handleAddress(result.text); + }, + function () { + showError("Scan faild"); + } + ); }); //Fire pageLoadHandler for discover (first page shown after start) @@ -1195,6 +1231,7 @@ function initTranslation() { 'loginPassword': 'Password:', 'loginButton': 'Login', 'registerButton': 'Create Profile', + 'discoverReadQrButton': 'Scan QRCode', 'mainPageYourProfileLink': 'Your Profile', 'mainPageYourProfileLinkDesc': 'Edit your profile', 'mainPageCurrentSongLink': 'Current Song', @@ -1274,6 +1311,7 @@ function initTranslation() { 'loginPassword': 'Passwort:', 'loginButton': 'Einloggen', 'registerButton': 'Erstelle Profil', + 'discoverReadQrButton': 'Fotografiere QRCode', 'mainPageYourProfileLink': 'Dein Profil', 'mainPageYourProfileLinkDesc': 'Bearbeite dein Profil', 'mainPageCurrentSongLink': 'Aktuelles Lied', From 0edc8f7faa62613fdd6d0b78e8d2c0c8a2413a49 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 1 Dec 2013 10:44:30 +0100 Subject: [PATCH 64/81] Webserver: -mod: config.xml cleanup --- PhoneGap/config.xml | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/PhoneGap/config.xml b/PhoneGap/config.xml index 802cde2f..d0ee02a0 100644 --- a/PhoneGap/config.xml +++ b/PhoneGap/config.xml @@ -31,31 +31,6 @@ - - - - - + \ No newline at end of file From b7ab42949e8b28f7425f308c7c06f069025257d1 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 1 Dec 2013 12:37:54 +0100 Subject: [PATCH 65/81] Webserver: -fix: Profile changes are reset on server restart --- Vocaluxe/Base/Server/CVocaluxeServer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index 380fe414..820318b1 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -256,6 +256,8 @@ namespace Vocaluxe.Base.Server if (existingProfile != null) { CProfiles.EditProfile(newProfile); + CProfiles.Update(); + CProfiles.SaveProfiles(); } else { @@ -607,7 +609,6 @@ namespace Vocaluxe.Base.Server #region user management - private static bool _ValidatePassword(int profileId, string password) { CProfile profile = CProfiles.GetProfile(profileId); @@ -688,6 +689,8 @@ namespace Vocaluxe.Base.Server profile.UserRoles = userRole; CProfiles.EditProfile(profile); + CProfiles.Update(); + CProfiles.SaveProfiles(); } private static int _GetUserIdFromUsername(string username) From 6c6a6578bdeec695b34852c6135c273dc1f23a23 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 1 Dec 2013 13:04:39 +0100 Subject: [PATCH 66/81] Webserver: -mod: set request timeout to 10 seconds --- Vocaluxe/Website/js/main.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index bbf75f3a..252a32be 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -1056,6 +1056,10 @@ function request(data, message) { if ((typeof message) == "undefined" || message == null) { message = "Loading..."; } + + if ((typeof data.timeout) == "undefined") { + data.timeout = 10000; //10 sec. timeout + } if (message != "noOverlay") { if (i18n.t) { From f00f3eb5ad5ea0945bbf9d845883bfc925acdcc9 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 1 Dec 2013 13:22:51 +0100 Subject: [PATCH 67/81] Webserver: -fix: Messages with dots were not translated -fix: request extrenal may not work --- Vocaluxe/Website/js/main.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index 252a32be..37af5f99 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -1062,12 +1062,13 @@ function request(data, message) { } if (message != "noOverlay") { + var message2 = message; if (i18n.t) { - message = i18n.t(message) || message; + message2 = i18n.t(message2); } $('div[data-role="content"]').wrap('
                                                '); $.mobile.loading('show', { - text: message, + text: message2, textVisible: true }); } @@ -1306,7 +1307,8 @@ function initTranslation() { 'discoverConnectHeader': 'Connect to server', 'discoverConnectServerAddress': 'Serveraddress:', 'discoverConnectButton': 'Connect', - 'Checking...': 'Checking...' + 'Checking...': 'Checking...', + 'timeout': 'Timeout' } }, "de": { @@ -1386,14 +1388,17 @@ function initTranslation() { 'discoverConnectHeader': 'Verbinde zum Server', 'discoverConnectServerAddress': 'Serveradresse:', 'discoverConnectButton': 'Verbinden', - 'Checking...': 'Prüfen...' + 'Checking...': 'Prüfen...', + 'timeout': 'Zeitüberschreitung' } } }; $.i18n.init({ resStore: translations, lng: "de", - fallbackLng: 'en' + fallbackLng: 'en', + keyseparator: '::', + nsseparator: ':::' }).done(function () { $('body').i18n(); }); From 43be5ff5cfb5886b6686bdec745efcb8d2add521 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 1 Dec 2013 13:33:22 +0100 Subject: [PATCH 68/81] Webserver: -add: detect user language automatically --- Vocaluxe/Website/js/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index 37af5f99..c88c907d 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -1056,7 +1056,7 @@ function request(data, message) { if ((typeof message) == "undefined" || message == null) { message = "Loading..."; } - + if ((typeof data.timeout) == "undefined") { data.timeout = 10000; //10 sec. timeout } @@ -1395,7 +1395,7 @@ function initTranslation() { }; $.i18n.init({ resStore: translations, - lng: "de", + supportedLngs: ['en', 'de'], fallbackLng: 'en', keyseparator: '::', nsseparator: ':::' From e713afa8e232d720213e452629bb5dbbf394fb35 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 1 Dec 2013 14:17:13 +0100 Subject: [PATCH 69/81] Webserver: -fix: translation destroys the design of the buttons on the first screen --- Vocaluxe/Website/js/main.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index c88c907d..7ad305a6 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -1393,6 +1393,13 @@ function initTranslation() { } } }; + + //repair broken buttons on the first page (get broken while translating) + var repairButtons = function () { + $($('#discoverConnect')[0].childNodes).wrap(' '); + $($('#discoverReadQr')[0].childNodes).wrap(' '); + }; + $.i18n.init({ resStore: translations, supportedLngs: ['en', 'de'], @@ -1401,5 +1408,6 @@ function initTranslation() { nsseparator: ':::' }).done(function () { $('body').i18n(); + repairButtons(); }); } \ No newline at end of file From 92012cf45e0dc183e3aa4c76873cd696939e8f13 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 1 Dec 2013 15:09:18 +0100 Subject: [PATCH 70/81] Webserver: -mod: disable discover server (yet not implemented in clientapp) --- Vocaluxe/Base/Server/CVocaluxeServer.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index 820318b1..27c79700 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -37,15 +37,12 @@ namespace Vocaluxe.Base.Server static class CVocaluxeServer { private static CServer _Server; - private static CDiscover _Discover; - private static Dictionary _Clients; + //private static CDiscover _Discover; public static readonly CControllerFramework Controller = new CControllerFramework(); public static void Init() { - _Clients = new Dictionary(); - _Server = new CServer(CConfig.ServerPort, CConfig.ServerEncryption == EOffOn.TR_CONFIG_ON); CServer.SendKeyEvent = _SendKeyEvent; @@ -72,7 +69,7 @@ namespace Vocaluxe.Base.Server CServer.RemovePlaylist = _RemovePlaylist; CServer.AddPlaylist = _AddPlaylist; - _Discover = new CDiscover(CConfig.ServerPort, CCommands.BroadcastKeyword); + //_Discover = new CDiscover(CConfig.ServerPort, CCommands.BroadcastKeyword); Controller.Init(); } @@ -81,15 +78,14 @@ 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(); + //_Discover.Stop(); } private static bool _SendKeyEvent(string key) From 924f45c6d0f6253ae99617f3abe50743c5b5798b Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 1 Dec 2013 23:11:13 +0100 Subject: [PATCH 71/81] Webserver: -mod: set header for browser caching for image requests --- ClientServerLib/ClientServerLib/CWebservice.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs index 7a6d4a3d..d910dc6d 100644 --- a/ClientServerLib/ClientServerLib/CWebservice.cs +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -1,4 +1,5 @@ using System; +using System.Net; using System.ServiceModel; using System.ServiceModel.Web; using System.IO; @@ -217,6 +218,10 @@ namespace ServerLib 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); @@ -237,6 +242,10 @@ namespace ServerLib 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); From 60a8c59b7d64febec242181309ecff51e074cc0a Mon Sep 17 00:00:00 2001 From: lukeIam Date: Sun, 1 Dec 2013 23:19:07 +0100 Subject: [PATCH 72/81] Webserver: -mod: also use cacheing headers for other resources --- ClientServerLib/ClientServerLib/CWebservice.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs index d910dc6d..c0a28811 100644 --- a/ClientServerLib/ClientServerLib/CWebservice.cs +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -177,6 +177,10 @@ namespace ServerLib 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); @@ -198,6 +202,10 @@ namespace ServerLib 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); From 304529f396df96f047adb4d9b46f0997a9eaedba Mon Sep 17 00:00:00 2001 From: lukeIam Date: Tue, 3 Dec 2013 19:35:30 +0100 Subject: [PATCH 73/81] Webserver: -fix: Password and Roles are not saved. --- Vocaluxe/Base/Server/CVocaluxeServer.cs | 2 +- VocaluxeLib/Profile/CProfile.cs | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index 27c79700..eaf4f15e 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -239,7 +239,7 @@ namespace Vocaluxe.Base.Server else { RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); - byte[] buffer = new byte[128]; + byte[] buffer = new byte[32]; rng.GetNonZeroBytes(buffer); byte[] salt = buffer; byte[] hashedPassword = _Hash((new UTF8Encoding()).GetBytes(profile.Password), salt); diff --git a/VocaluxeLib/Profile/CProfile.cs b/VocaluxeLib/Profile/CProfile.cs index 85d32dc7..48cc4bba 100644 --- a/VocaluxeLib/Profile/CProfile.cs +++ b/VocaluxeLib/Profile/CProfile.cs @@ -59,7 +59,7 @@ namespace VocaluxeLib.Profile Active = EOffOn.TR_CONFIG_ON; AvatarFileName = String.Empty; - FileName = String.Empty; + FileName = String.Empty; } public bool LoadProfile() @@ -90,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 = Encoding.UTF8.GetBytes(passwordHash); + string passwordSalt; + xmlReader.GetValue("//root/Info/PasswordHash", out passwordSalt, ""); + PasswordSalt = Encoding.UTF8.GetBytes(passwordSalt); + string userRoles; + xmlReader.GetValue("//root/Info/UserRoles", out userRoles, "0"); + Int32.TryParse(userRoles, out UserRoles); return true; } @@ -151,6 +159,9 @@ 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)); + writer.WriteElementString("PasswordHash", Encoding.UTF8.GetString(PasswordHash)); + writer.WriteElementString("PasswordSalt", Encoding.UTF8.GetString(PasswordSalt)); + writer.WriteElementString("UserRoles", UserRoles.ToString()); writer.WriteEndElement(); writer.WriteEndElement(); //end of root From ad717ea56ed519764f474261f3c6bcd1cad5a344 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Tue, 3 Dec 2013 20:11:08 +0100 Subject: [PATCH 74/81] Webserver: -fix: problems setting the password and login --- Vocaluxe/Base/Server/CVocaluxeServer.cs | 1 + VocaluxeLib/Profile/CProfile.cs | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index eaf4f15e..f77acf4b 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -178,6 +178,7 @@ namespace Vocaluxe.Base.Server { newProfile = new CProfile { + ID = existingProfile.ID, Active = existingProfile.Active, AvatarFileName = existingProfile.AvatarFileName, Avatar = existingProfile.Avatar, diff --git a/VocaluxeLib/Profile/CProfile.cs b/VocaluxeLib/Profile/CProfile.cs index 48cc4bba..bae8a241 100644 --- a/VocaluxeLib/Profile/CProfile.cs +++ b/VocaluxeLib/Profile/CProfile.cs @@ -92,10 +92,10 @@ namespace VocaluxeLib.Profile xmlReader.TryGetEnumValue("//root/Info/Active", ref Active); string passwordHash; xmlReader.GetValue("//root/Info/PasswordHash", out passwordHash, ""); - PasswordHash = Encoding.UTF8.GetBytes(passwordHash); + PasswordHash = !string.IsNullOrEmpty(passwordHash) ? Convert.FromBase64String(passwordHash) : null; string passwordSalt; xmlReader.GetValue("//root/Info/PasswordHash", out passwordSalt, ""); - PasswordSalt = Encoding.UTF8.GetBytes(passwordSalt); + PasswordSalt = !string.IsNullOrEmpty(passwordSalt) ? Convert.FromBase64String(passwordSalt) : null; string userRoles; xmlReader.GetValue("//root/Info/UserRoles", out userRoles, "0"); Int32.TryParse(userRoles, out UserRoles); @@ -159,8 +159,14 @@ 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)); - writer.WriteElementString("PasswordHash", Encoding.UTF8.GetString(PasswordHash)); - writer.WriteElementString("PasswordSalt", Encoding.UTF8.GetString(PasswordSalt)); + 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(); From 252ef113cef23562cc624676bcc07c708452c83a Mon Sep 17 00:00:00 2001 From: lukeIam Date: Tue, 3 Dec 2013 20:23:13 +0100 Subject: [PATCH 75/81] Webserver: -fix: used PasswordHash instead of PasswordSalt once --- VocaluxeLib/Profile/CProfile.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VocaluxeLib/Profile/CProfile.cs b/VocaluxeLib/Profile/CProfile.cs index bae8a241..466de93f 100644 --- a/VocaluxeLib/Profile/CProfile.cs +++ b/VocaluxeLib/Profile/CProfile.cs @@ -94,7 +94,7 @@ namespace VocaluxeLib.Profile xmlReader.GetValue("//root/Info/PasswordHash", out passwordHash, ""); PasswordHash = !string.IsNullOrEmpty(passwordHash) ? Convert.FromBase64String(passwordHash) : null; string passwordSalt; - xmlReader.GetValue("//root/Info/PasswordHash", out 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"); From cdcd3d201fef3f12e89cc891b36fd77be1ce2551 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Tue, 3 Dec 2013 20:26:32 +0100 Subject: [PATCH 76/81] Webserver: -fix: new profile config files were created instead og using the old ones --- Vocaluxe/Base/Server/CVocaluxeServer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index f77acf4b..1a323dd9 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -179,6 +179,7 @@ namespace Vocaluxe.Base.Server newProfile = new CProfile { ID = existingProfile.ID, + FileName = existingProfile.FileName, Active = existingProfile.Active, AvatarFileName = existingProfile.AvatarFileName, Avatar = existingProfile.Avatar, From d4552d586026fff2d9c110d8707569e6f26c242c Mon Sep 17 00:00:00 2001 From: lukeIam Date: Tue, 3 Dec 2013 20:56:38 +0100 Subject: [PATCH 77/81] Webserver: -mod: removed send char funktion from app -mod: little style fix --- Vocaluxe/Website/css/style.css | 6 +++++- Vocaluxe/Website/index.html | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Vocaluxe/Website/css/style.css b/Vocaluxe/Website/css/style.css index e3210c83..95fde798 100644 --- a/Vocaluxe/Website/css/style.css +++ b/Vocaluxe/Website/css/style.css @@ -71,7 +71,11 @@ } .ui-input-search { - background: #ffffff !important; + background: #6E6E6E !important; +} + +.ui-listview-filter { + background: #000000 !important; } .ui-custom-errorIcon { diff --git a/Vocaluxe/Website/index.html b/Vocaluxe/Website/index.html index bf48dff2..256db6f1 100644 --- a/Vocaluxe/Website/index.html +++ b/Vocaluxe/Website/index.html @@ -298,10 +298,10 @@
                                                -
                                                +
                                                From 14835e2e24cce61ab04c9cb6892d4f65b9a70a1e Mon Sep 17 00:00:00 2001 From: lukeIam Date: Fri, 6 Dec 2013 17:03:08 +0100 Subject: [PATCH 78/81] Webserver: -mod: translations are now in external json files --- .../ClientServerLib/CWebservice.cs | 27 ++- .../ClientServerLib/ICWebservice.cs | 6 + Vocaluxe/Vocaluxe.csproj | 6 + Vocaluxe/Website/js/main.js | 205 +++--------------- Vocaluxe/Website/locales/de.json | 80 +++++++ Vocaluxe/Website/locales/en.json | 80 +++++++ 6 files changed, 225 insertions(+), 179 deletions(-) create mode 100644 Vocaluxe/Website/locales/de.json create mode 100644 Vocaluxe/Website/locales/en.json diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs index c0a28811..8da01ab2 100644 --- a/ClientServerLib/ClientServerLib/CWebservice.cs +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -269,6 +269,31 @@ namespace ServerLib 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); @@ -428,6 +453,6 @@ namespace ServerLib } #endregion - + } } diff --git a/ClientServerLib/ClientServerLib/ICWebservice.cs b/ClientServerLib/ClientServerLib/ICWebservice.cs index c272915f..3e79d8ce 100644 --- a/ClientServerLib/ClientServerLib/ICWebservice.cs +++ b/ClientServerLib/ClientServerLib/ICWebservice.cs @@ -91,6 +91,12 @@ namespace ServerLib 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, diff --git a/Vocaluxe/Vocaluxe.csproj b/Vocaluxe/Vocaluxe.csproj index 168d0759..6b0f0c20 100644 --- a/Vocaluxe/Vocaluxe.csproj +++ b/Vocaluxe/Vocaluxe.csproj @@ -304,6 +304,12 @@ + + PreserveNewest + + + PreserveNewest + diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index 7ad305a6..bfc14a85 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -7,24 +7,34 @@ var playlistRequestName = ""; var customSelectPlaylistSongCallback = null; var sessionId = ""; var serverBaseAddress = ""; +var tranlationLoaded; if (document.location.protocol == "file:") { if (typeof (window.deviceAndJqmLoaded) == "undefined") { window.deviceAndJqmLoaded = $.Deferred(); } window.deviceAndJqmLoaded.done(function () { - start(); + preStart(); }); } else { $(document).ready(function () { + preStart(); + }); +} + +function preStart() { + tranlationLoaded = $.Deferred(); + + initTranslation(); + + tranlationLoaded.done(function () { + translate(); start(); }); } - function start() { replaceTransitionHandler(); - initTranslation(); initPageLoadHandler(); initKeyboardPageHandler(); initMainPageHandler(); @@ -1229,185 +1239,24 @@ function showWikipedia(artist) { } function initTranslation() { - var translations = { - "en": { - translation: { - '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...', - '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' - } - }, - "de": { - translation: { - '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...', - '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' - } - } - }; - + $.i18n.init({ + resGetPath: 'locales/__lng__.json', + supportedLngs: ['en', 'de'], + fallbackLng: 'en', + keyseparator: '::', + nsseparator: ':::' + }).done(function () { + tranlationLoaded.resolve(); + }); +} + +function translate() { //repair broken buttons on the first page (get broken while translating) var repairButtons = function () { $($('#discoverConnect')[0].childNodes).wrap(' '); $($('#discoverReadQr')[0].childNodes).wrap(' '); }; - $.i18n.init({ - resStore: translations, - supportedLngs: ['en', 'de'], - fallbackLng: 'en', - keyseparator: '::', - nsseparator: ':::' - }).done(function () { - $('body').i18n(); - repairButtons(); - }); + $('body').i18n(); + repairButtons(); } \ No newline at end of file diff --git a/Vocaluxe/Website/locales/de.json b/Vocaluxe/Website/locales/de.json new file mode 100644 index 00000000..ddf85d71 --- /dev/null +++ b/Vocaluxe/Website/locales/de.json @@ -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" +} \ No newline at end of file diff --git a/Vocaluxe/Website/locales/en.json b/Vocaluxe/Website/locales/en.json new file mode 100644 index 00000000..c6b28fd0 --- /dev/null +++ b/Vocaluxe/Website/locales/en.json @@ -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" +} \ No newline at end of file From b4aa459f9a587214db62692a7c50885232024c25 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Wed, 11 Dec 2013 09:00:20 +0100 Subject: [PATCH 79/81] Fixed line endings --- Vocaluxe/app.config | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Vocaluxe/app.config b/Vocaluxe/app.config index 2063f6ab..7fb031b0 100644 --- a/Vocaluxe/app.config +++ b/Vocaluxe/app.config @@ -1,6 +1,6 @@ - - - - - - + + + + + + From fc0fad5248da154953001af4083c4d8e301c3fca Mon Sep 17 00:00:00 2001 From: lukeIam Date: Wed, 11 Dec 2013 20:43:57 +0100 Subject: [PATCH 80/81] -Correct line endings 2 --- Vocaluxe/Base/CSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Vocaluxe/Base/CSettings.cs b/Vocaluxe/Base/CSettings.cs index 14790c1e..7f63c97e 100644 --- a/Vocaluxe/Base/CSettings.cs +++ b/Vocaluxe/Base/CSettings.cs @@ -102,7 +102,7 @@ namespace Vocaluxe.Base #endif Path.Combine(DataPath, FolderProfiles) }; - public static string FolderPhotos = "Photos"; + public static string FolderPhotos = "Photos"; public const string FolderSongs = "Songs"; public const string FolderSounds = "Sounds"; public const string FolderLanguages = "Languages"; From fc35885425c84bf7d4049df3bd7551cf9d36bb24 Mon Sep 17 00:00:00 2001 From: lukeIam Date: Fri, 13 Dec 2013 18:26:47 +0100 Subject: [PATCH 81/81] - Fixed rebase/merge errors --- Vocaluxe.sln | 81 +++---------------------- Vocaluxe/Base/Server/CCommands.cs | 41 ------------- Vocaluxe/Base/Server/CVocaluxeServer.cs | 4 +- Vocaluxe/Vocaluxe.csproj | 2 +- 4 files changed, 13 insertions(+), 115 deletions(-) diff --git a/Vocaluxe.sln b/Vocaluxe.sln index ccccbf04..9b95b426 100644 --- a/Vocaluxe.sln +++ b/Vocaluxe.sln @@ -1,4 +1,3 @@ - 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}" @@ -64,10 +63,6 @@ Global {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x64.Build.0 = DebugLinux|x64 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x86.ActiveCfg = DebugLinux|x86 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x86.Build.0 = DebugLinux|x86 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|Any CPU.Build.0 = DebugWin|x86 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|Mixed Platforms.ActiveCfg = DebugWin|x86 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|Mixed Platforms.Build.0 = DebugWin|x86 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x64.ActiveCfg = DebugWin|x64 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x64.Build.0 = DebugWin|x64 {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x86.ActiveCfg = DebugWin|x86 @@ -104,135 +99,79 @@ Global {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|Any CPU.ActiveCfg = DebugLinux|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|Mixed Platforms.ActiveCfg = DebugLinux|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|Mixed Platforms.Build.0 = DebugLinux|x86 {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|x64.ActiveCfg = DebugLinux|x64 {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|x64.Build.0 = DebugLinux|x64 {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|x86.ActiveCfg = DebugLinux|x86 {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|x86.Build.0 = DebugLinux|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|Mixed Platforms.ActiveCfg = DebugWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|Mixed Platforms.Build.0 = DebugWin|x86 {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|x64.ActiveCfg = DebugWin|x64 {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}.ReleaseLinux|Any CPU.ActiveCfg = ReleaseLinux|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|Mixed Platforms.ActiveCfg = ReleaseLinux|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|Mixed Platforms.Build.0 = ReleaseLinux|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 {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|x86.Build.0 = ReleaseLinux|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|Mixed Platforms.ActiveCfg = ReleaseWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|Mixed Platforms.Build.0 = ReleaseWin|x86 {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|Any CPU.ActiveCfg = DebugLinux|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|Mixed Platforms.ActiveCfg = DebugLinux|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|Mixed Platforms.Build.0 = DebugLinux|x86 {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|x64.ActiveCfg = DebugLinux|x64 {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|x64.Build.0 = DebugLinux|x64 {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|x86.ActiveCfg = DebugLinux|x86 {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|x86.Build.0 = DebugLinux|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|Any CPU.ActiveCfg = DebugWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|Mixed Platforms.ActiveCfg = DebugWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|Mixed Platforms.Build.0 = DebugWin|x86 {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|x64.ActiveCfg = DebugWin|x64 {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}.ReleaseLinux|Any CPU.ActiveCfg = ReleaseLinux|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|Mixed Platforms.ActiveCfg = ReleaseLinux|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|Mixed Platforms.Build.0 = ReleaseLinux|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 {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|x86.Build.0 = ReleaseLinux|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|Any CPU.ActiveCfg = ReleaseWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|Mixed Platforms.ActiveCfg = ReleaseWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|Mixed Platforms.Build.0 = ReleaseWin|x86 {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {ED007796-367F-4142-AA55-5450C7645C2C}.DebugLinux|Any CPU.ActiveCfg = DebugWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.DebugLinux|Mixed Platforms.ActiveCfg = DebugWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.DebugLinux|Mixed Platforms.Build.0 = DebugWin|Win32 {ED007796-367F-4142-AA55-5450C7645C2C}.DebugLinux|x64.ActiveCfg = DebugWin|x64 {ED007796-367F-4142-AA55-5450C7645C2C}.DebugLinux|x86.ActiveCfg = DebugWin|x64 - {ED007796-367F-4142-AA55-5450C7645C2C}.DebugWin|Any CPU.ActiveCfg = DebugWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.DebugWin|Mixed Platforms.ActiveCfg = DebugWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.DebugWin|Mixed Platforms.Build.0 = DebugWin|Win32 {ED007796-367F-4142-AA55-5450C7645C2C}.DebugWin|x64.ActiveCfg = DebugWin|x64 {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}.ReleaseLinux|Any CPU.ActiveCfg = ReleaseWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseLinux|Mixed Platforms.ActiveCfg = ReleaseWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseLinux|Mixed Platforms.Build.0 = ReleaseWin|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|Any CPU.ActiveCfg = ReleaseWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseWin|Mixed Platforms.ActiveCfg = ReleaseWin|Win32 - {ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseWin|Mixed Platforms.Build.0 = ReleaseWin|Win32 {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|Any CPU.ActiveCfg = Debug|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|Any CPU.Build.0 = Debug|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|Mixed Platforms.ActiveCfg = Debug|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|Mixed Platforms.Build.0 = Debug|Any CPU {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|Any CPU.ActiveCfg = Debug|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|Any CPU.Build.0 = Debug|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|Mixed Platforms.ActiveCfg = Debug|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|Mixed Platforms.Build.0 = 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}.ReleaseLinux|Any CPU.ActiveCfg = Release|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|Any CPU.Build.0 = Release|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|Mixed Platforms.ActiveCfg = Release|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|Mixed Platforms.Build.0 = Release|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|Any CPU.ActiveCfg = Release|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|Any CPU.Build.0 = Release|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|Mixed Platforms.ActiveCfg = Release|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|Mixed Platforms.Build.0 = 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|Any CPU.ActiveCfg = Debug|Any CPU - {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugLinux|Any CPU.Build.0 = Debug|Any CPU - {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugLinux|Mixed Platforms.ActiveCfg = Debug|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|Any CPU.ActiveCfg = Debug|Any CPU - {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugWin|Any CPU.Build.0 = Debug|Any CPU - {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugWin|Mixed Platforms.ActiveCfg = Debug|Any CPU - {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugWin|Mixed Platforms.Build.0 = 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}.ReleaseLinux|Any CPU.ActiveCfg = Release|Any CPU - {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseLinux|Any CPU.Build.0 = Release|Any CPU - {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseLinux|Mixed Platforms.ActiveCfg = Release|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|Any CPU.ActiveCfg = Release|Any CPU - {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|Any CPU.Build.0 = Release|Any CPU - {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|Mixed Platforms.ActiveCfg = Release|Any CPU - {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|Mixed Platforms.Build.0 = 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 diff --git a/Vocaluxe/Base/Server/CCommands.cs b/Vocaluxe/Base/Server/CCommands.cs index 5a2f545d..6e6f0e66 100644 --- a/Vocaluxe/Base/Server/CCommands.cs +++ b/Vocaluxe/Base/Server/CCommands.cs @@ -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 obj) { diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index 1a323dd9..d64bbf4d 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -442,8 +442,8 @@ namespace Vocaluxe.Base.Server { result.Title = song.Title; result.Artist = song.Artist; - result.Genre = song.Genre.FirstOrDefault(); - result.Language = song.Language.FirstOrDefault(); + result.Genre = song.Genres.FirstOrDefault(); + result.Language = song.Languages.FirstOrDefault(); result.Year = song.Year; result.IsDuet = song.IsDuet; result.SongId = song.ID; diff --git a/Vocaluxe/Vocaluxe.csproj b/Vocaluxe/Vocaluxe.csproj index 6b0f0c20..2dec4b8e 100644 --- a/Vocaluxe/Vocaluxe.csproj +++ b/Vocaluxe/Vocaluxe.csproj @@ -424,7 +424,7 @@ False - Microsoft .NET Framework 4 Client Profile %28x86 und x64%29 und Update für .NET Framework 4 %28KB2468871%29 + Microsoft .NET Framework 4 Client Profile %28x86 und x64%29 und Update für .NET Framework 4 %28KB2468871%29 true