/// <summary>Compares two InviteCode objects</summary> /// <param name="a">InviteCode a</param> /// <param name="b">InviteCode b</param> /// <returns>Returns true if the two InviteCode objects are identical, false otherwise</returns> public static bool AreIdentical(InviteCode a, InviteCode b) { try { if (a == null && b == null) { return(true); } if (a == null || b == null) { return(false); } if (a.SessionId == b.SessionId && string.CompareOrdinal(a.InviterAlias, b.InviterAlias) == 0 && string.CompareOrdinal(a.InviterShortDeviceId, b.InviterShortDeviceId) == 0) { return(true); } } catch (Exception ex) { Logger.Log(ex, new StackFrame(0, true)); } return(false); }
/// <summary>Returns an InviteCode object from a free-form string invite message</summary> /// <param name="text">The invite message</param> /// <returns>Returns an InviteCode object from a free-form string invite message</returns> public static InviteCode Parse(string text) { if (string.IsNullOrEmpty(text) || text.IndexOf("rndup://", StringComparison.Ordinal) == -1) { MessageBoxHelper.Show(Strings.GetStringResource("MissingInviteCode"), string.Empty, false); return(null); } // Parse the invite, inviter's short device id code and inviter's name from the invite text. // The invite code will look like this: "rndup://sessionId?did=shortDeviceId&nme=inviter" // // sessionId = the Azure Session table row id of the session // did = the inviter's short device id (8 chars). Used as a basic security "pin code" // nme = the inviter's name/alias (50 chars max, variable length, http encoded) var inviteCode = new InviteCode(); try { var inviteCodeText = text.Substring(text.IndexOf("rndup://", StringComparison.Ordinal)).Trim(); // We now have: "rndup://xxx?did=yyyyyyyy&nme=nnnn {anything}", // where y is an 8-char alphanumeric (a..z, A..Z or 0..9), xxx is an int, nnnn is a var number of chars, var tmp = inviteCodeText.Substring("rndup://".Length); // --> "xxx?did=yyyyyyyy&nme=nnnn {anything}" var queryIndex = tmp.IndexOf("?did=", StringComparison.Ordinal); if (queryIndex == -1) { throw new Exception(); } // Pick-off the session id var tmpSessionId = tmp.Remove(queryIndex); inviteCode.SessionId = int.Parse(tmpSessionId); // Now get the 8-character (it's always 8-chars, guaranteed) short device id tmp = tmp.Substring(queryIndex + "?did=".Length); // --> "yyyyyyyy&nme=nnnn {anything}" inviteCode.InviterShortDeviceId = tmp.Substring(0, 8); // Now get the variable-length inviter name tmp = tmp.Substring("yyyyyyyy&nme=".Length); // --> "nnnn {anything}" // Find the end of the custom uri - this will be a space, or the end of the string queryIndex = tmp.IndexOf(" ", StringComparison.Ordinal); inviteCode.InviterAlias = queryIndex == -1 ? tmp : tmp.Substring(0, queryIndex); inviteCode.InviterAlias = Uri.UnescapeDataString(inviteCode.InviterAlias); return(inviteCode); } catch (Exception ex) { MessageBoxHelper.Show(Strings.GetStringResource("BadInviteCode"), string.Empty, false); Logger.Log(ex, new StackFrame(0, true)); return(null); } }
/// <summary> /// If the app was launched using our custom uri association - pick off the /// session id, device id and inviter's name parameters and pass them in the /// InviteCodeHelper.LaunchInviteCode field to the view model /// /// If using the uri association, the incoming uri will the following format: /// /// ReSharper disable CSharpWarnings::CS1570 /// /// /Protocol?encodedLaunchUri=rndup://sid/?did=yyyy&nme=nnnn /// /// ReSharper restore CSharpWarnings::CS1570 /// /// where sid = session id, did = short device id, nme = inviter name /// </summary> /// <param name="uri">The uri passed to the app</param> /// <returns>Returns a URI to be used to launch the app's start-up page</returns> public override Uri MapUri(Uri uri) { try { // Handle Uri mapping... var uriText = HttpUtility.UrlDecode(uri.ToString()); // Parse the invite code text. Result may be null, which is valid (= no startup params) var tmpLaunchCode = InviteCodeHelper.ParseUriAssociation(uriText); // Have we already found this invite code (for some reason MapUri sometimes gets called twice)? if (!InviteCode.AreIdentical(tmpLaunchCode, InviteCodeHelper.LaunchInviteCode)) { InviteCodeHelper.LaunchInviteCode = tmpLaunchCode; if (Debugger.IsAttached && InviteCodeHelper.LaunchInviteCode != null) { var tmp = string.Format("Detected launch invite code: SessionId = {0}, InviterShortDeviceId = {1}, InviterAlias = {2}", InviteCodeHelper.LaunchInviteCode.SessionId, InviteCodeHelper.LaunchInviteCode.InviterShortDeviceId, InviteCodeHelper.LaunchInviteCode.InviterAlias); Logger.Log(tmp); } } if (tmpLaunchCode == null) { return(uri); // Just use the default navigation uri (there were no params) } // Re-construct the view uri, having picked off the start-up params var launchUri = string.Format("/View\\MainView.xaml"); return(new Uri(launchUri, UriKind.Relative)); } catch (Exception ex) { Logger.Log(ex, new StackFrame(0, true)); var launchUri = string.Format("/View\\MainView.xaml"); return(new Uri(launchUri, UriKind.Relative)); } }
/// <summary>Returns an InviteCode object from a custom uri association which may have been used to launch the app</summary> /// <param name="text">The invite message</param> /// <returns>Returns an InviteCode object from a custom uri association (see UriMapper)</returns> public static InviteCode ParseUriAssociation(string text) { if (string.IsNullOrEmpty(text) || text.IndexOf("rndup://", StringComparison.Ordinal) == -1) { return(null); } // Parse the invite, inviter's short device id code and inviter's name from the uri association text... // The uri text will look like this: "/Protocol?encodedLaunchUri=rndup://sid/?did=yyyyyyyy&nme=nnnnn" // or this: "/Protocol?encodedLaunchUri=rndup://sid?did=yyyyyyyy&nme=nnnnn" var inviteCode = new InviteCode(); try { var inviteCodeText = text.Substring(text.IndexOf("rndup://", StringComparison.Ordinal)).Trim(); // We now have: "rndup://sid/?did=yyyyyyyy&nme=nnnn {anything}", or "sid?did=yyyy&nme=nnnn {anything}" // where y is an 8-char alphanumeric (a..z, A..Z or 0..9), xxx is an int, nnnn is a var number of chars, var tmp = inviteCodeText.Substring("rndup://".Length); // --> "sid/?did=yyyyyyyy&nme=nnnn {anything}" or "sid?did=yyyyyyyy&nme=nnnn {anything}" // Decide if the leading "/" is present int didLength; var queryIndex = tmp.IndexOf("/?did=", StringComparison.Ordinal); if (queryIndex == -1) { queryIndex = tmp.IndexOf("?did=", StringComparison.Ordinal); if (queryIndex == -1) { throw new Exception(); } didLength = "?did=".Length; } else { didLength = "/?did=".Length; } // Pick-off the session id var tmpSessionId = tmp.Remove(queryIndex); inviteCode.SessionId = int.Parse(tmpSessionId); // Now get the 8-character (it's always 8-chars, guaranteed) short device id tmp = tmp.Substring(queryIndex + didLength); // --> "yyyyyyyy&nme=nnnn {anything}" inviteCode.InviterShortDeviceId = tmp.Substring(0, 8); // Now get the variable-length inviter name tmp = tmp.Substring("yyyyyyyy&nme=".Length); // --> "nnnn {anything}" // Find the end of the custom uri - this will be a space, or the end of the string queryIndex = tmp.IndexOf(" ", StringComparison.Ordinal); inviteCode.InviterAlias = queryIndex == -1 ? tmp : tmp.Substring(0, queryIndex); inviteCode.InviterAlias = Uri.UnescapeDataString(inviteCode.InviterAlias); } catch (Exception ex) { Logger.Log(ex, new StackFrame(0, true)); return(null); } return(inviteCode); }