Created
May 2, 2011 01:47
-
-
Save takeshik/951086 to your computer and use it in GitHub Desktop.
MetaTweet (new) Requests code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| private static void Main() | |
| { | |
| var fragments = CreateFragments(Regex.Matches( | |
| @"/$a=1$b==44OG44K544OILyEv44OG44K544OI(/!/obj/activities?query=name:ScreenName value:bob/@Single().Account/-or/$c=3$d=4!twitter/users/show?screen_name=bob/)/!/.xml?encoding=utf-8&format=oneline&b64==44OG44K544OILyEv44OG44K544OI", | |
| @"(/(?:\$[^!@\(\)\-]+)?[!@\(\)\-])(.*?(?=/[\$!@\(\)\-]|$))" | |
| ).Cast<Match>().Select(m => new [] { m.Groups[1].Value, m.Groups[2].Value, })).Dump(); | |
| } | |
| private static IDictionary<String, String> GetVariableTable(String str) | |
| { | |
| return str[1] == '$' | |
| ? str | |
| .Substring(2, str.Length - 3) | |
| .Split('$') | |
| .Select(p => p.Split('=')) | |
| .ToDictionary(p => p[0], p => p.Length == 3 | |
| ? Encoding.UTF8.GetString(Convert.FromBase64String(p[2].Length % 4 == 0 | |
| ? p[2] | |
| : p[2] + new String('=', 4 - (p[2].Length % 4)) | |
| )) | |
| : p[1] | |
| ) | |
| : new Dictionary<String, String>(); | |
| } | |
| private static IEnumerable<Fragment> CreateFragments(IEnumerable<String[]> input) | |
| { | |
| Stack<Tuple<IDictionary<String, String>, LinkedList<Fragment>>> stack | |
| = new Stack<Tuple<IDictionary<String, String>, LinkedList<Fragment>>>(); | |
| foreach (String[] data in input) | |
| { | |
| Fragment fragment = null; | |
| switch (data[0].Last()) | |
| { | |
| case '(': | |
| stack.Push(Tuple.Create(GetVariableTable(data[0]), new LinkedList<Fragment>())); | |
| break; | |
| case ')': | |
| Tuple<IDictionary<String, String>, LinkedList<Fragment>> tuple = stack.Pop(); | |
| fragment = new ScopeFragment(tuple.Item1, tuple.Item2.ToArray()); | |
| break; | |
| case '!': | |
| Int32 index = data[1].IndexOf("?"); | |
| Dictionary<String, String> arguments = index != -1 | |
| ? data[1].Substring(index + 1).Split('&').Select(p => p.Split('=')).ToDictionary(p => p[0], p => p.Length == 3 | |
| ? Encoding.UTF8.GetString(Convert.FromBase64String(p[2].Length % 4 == 0 | |
| ? p[2] | |
| : p[2] + new String('=', 4 - (p[2].Length % 4)) | |
| )) | |
| : p[1] | |
| ) | |
| : new Dictionary<String, String>(); | |
| String flowName = data[1].First() == '/' ? "" : data[1].Substring(0, data[1].IndexOf('/')); | |
| String selector = data[1].Substring(flowName.Length, index != -1 ? index - flowName.Length : Int32.MaxValue); | |
| fragment = new FlowFragment(GetVariableTable(data[0]), flowName, selector, arguments); | |
| break; | |
| case '@': | |
| fragment = new CodeFragment(GetVariableTable(data[0]), data[1]); | |
| break; | |
| case '-': | |
| fragment = new ConjunctionFragment(GetVariableTable(data[0]), data[1]); | |
| break; | |
| default: | |
| break; | |
| } | |
| if (fragment != null) | |
| { | |
| if (stack.Any()) | |
| { | |
| stack.Peek().Item2.AddLast(fragment); | |
| } | |
| else | |
| { | |
| yield return fragment; | |
| } | |
| } | |
| } | |
| } | |
| #region Types | |
| public class Request | |
| { | |
| public IEnumerable<Fragment> Fragments | |
| { | |
| get; | |
| private set; | |
| } | |
| public String OriginalString | |
| { | |
| get; | |
| private set; | |
| } | |
| } | |
| public enum FragmentType | |
| { | |
| Unknown = 0, | |
| Flow, | |
| Code, | |
| Scope, | |
| Conjunction, | |
| } | |
| public abstract class Fragment | |
| { | |
| public abstract FragmentType Type | |
| { | |
| get; | |
| } | |
| public IDictionary<String, String> Variables | |
| { | |
| get; | |
| private set; | |
| } | |
| protected Fragment(IDictionary<String, String> variables) | |
| { | |
| this.Variables = variables ?? new Dictionary<String, String>(); | |
| } | |
| protected String GetVariablesString() | |
| { | |
| return String.Concat(this.Variables.Select(p => "$" + p.Key + "=" + p.Value)); | |
| } | |
| } | |
| public class ScopeFragment | |
| : Fragment | |
| { | |
| public override FragmentType Type | |
| { | |
| get | |
| { | |
| return FragmentType.Scope; | |
| } | |
| } | |
| public IEnumerable<Fragment> Fragments | |
| { | |
| get; | |
| private set; | |
| } | |
| public ScopeFragment(IDictionary<String, String> variables, params Fragment[] fragments) | |
| : base(variables) | |
| { | |
| this.Fragments = fragments; | |
| } | |
| public override String ToString() | |
| { | |
| return "/" + this.GetVariablesString() + "(" + String.Concat(this.Fragments.Select(f => f.ToString())) + "/)"; | |
| } | |
| } | |
| public class FlowFragment | |
| : Fragment | |
| { | |
| public override FragmentType Type | |
| { | |
| get | |
| { | |
| return FragmentType.Flow; | |
| } | |
| } | |
| public String FlowName | |
| { | |
| get; | |
| private set; | |
| } | |
| public String Selector | |
| { | |
| get; | |
| private set; | |
| } | |
| public IDictionary<String, String> Arguments | |
| { | |
| get; | |
| private set; | |
| } | |
| public FlowFragment(IDictionary<String, String> variables, String flowName, String selector, IDictionary<String, String> arguments) | |
| : base(variables) | |
| { | |
| this.FlowName = flowName; | |
| this.Selector = selector; | |
| this.Arguments = arguments; | |
| } | |
| public override String ToString() | |
| { | |
| return | |
| "/" + this.GetVariablesString() + | |
| "!" + this.FlowName + | |
| this.Selector + | |
| (this.Arguments.Any() ? "?" + String.Join("&", this.Arguments.Select(p => p.Key + "=" + p.Value)) : ""); | |
| } | |
| } | |
| public class CodeFragment | |
| : Fragment | |
| { | |
| public override FragmentType Type | |
| { | |
| get | |
| { | |
| return FragmentType.Code; | |
| } | |
| } | |
| public String Code | |
| { | |
| get; | |
| private set; | |
| } | |
| public CodeFragment(IDictionary<String, String> variables, String code) | |
| : base(variables) | |
| { | |
| this.Code = code; | |
| } | |
| public override String ToString() | |
| { | |
| return "/" + this.GetVariablesString() + "@" + this.Code; | |
| } | |
| } | |
| public class ConjunctionFragment | |
| : Fragment | |
| { | |
| public override FragmentType Type | |
| { | |
| get | |
| { | |
| return FragmentType.Conjunction; | |
| } | |
| } | |
| public String Name | |
| { | |
| get; | |
| private set; | |
| } | |
| public ConjunctionFragment(IDictionary<String, String> variables, String name) | |
| : base(variables) | |
| { | |
| this.Name = name; | |
| } | |
| public override String ToString() | |
| { | |
| return "/" + this.GetVariablesString() + "-" + this.Name; | |
| } | |
| } | |
| #endregion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment