private bool?conditionEval(string arg, NaviXVars vars)
        {
            bool? result = null;
            Match m      = ifParse.Match(arg);

            if (m.Success)
            {
                string lKey = m.Groups[1].Value;
                string oper = m.Groups[2].Value;
                string rraw = m.Groups[3].Value;
                if (oper == "=")
                {
                    oper = "==";
                }

                string rside = getValue(rraw, vars);
                result = NaviXStringEvaluator.Eval(vars[lKey], rside, oper);
            }
            else
            {
                result = !string.IsNullOrEmpty(vars[arg]);
            }

            return(result);
        }
 string getValue(string arg, NaviXVars vars)
 {
     if (arg.StartsWith("'"))
     {
         return(arg.Substring(1));
     }
     else
     {
         return(vars[arg]);
     }
 }
        private bool?evaluateIfBlock(string arg, NaviXVars vars)
        {
            Match m = multiIfTest.Match(arg);

            if (!m.Success)
            {
                return(conditionEval(arg, vars));
            }

            bool mFlag = true;

            while (mFlag)
            {
                m = conditionExtract.Match(arg);
                if (m.Success)
                {
                    string cond    = m.Groups[1].Value;
                    bool?  boolObj = conditionEval(cond, vars);
                    if (boolObj == null)
                    {
                        logError("error evaluating condition {0}", cond);
                        return(null);
                    }
                    if (boolObj == true)
                    {
                        arg = arg.Replace(cond, "\u0010");
                    }
                    else
                    {
                        arg = arg.Replace(cond, "\u0011");
                    }
                }
                else
                {
                    mFlag = false;
                }
            }
            arg = arg.Replace("\u0010", "True");
            arg = arg.Replace("\u0011", "False");
            bool result;

            if (bool.TryParse(arg, out result))
            {
                return(result);
            }
            else
            {
                logError("error evaluating result {0}", arg);
                return(null);
            }
        }
 string getValue(string arg, NaviXVars vars)
 {
     if (arg.StartsWith("'"))
         return arg.Substring(1);
     else
         return vars[arg];
 }
        private bool? conditionEval(string arg, NaviXVars vars)
        {
            bool? result = null;
            Match m = ifParse.Match(arg);
            if (m.Success)
            {
                string lKey = m.Groups[1].Value;
                string oper = m.Groups[2].Value;
                string rraw = m.Groups[3].Value;
                if (oper == "=")
                    oper = "==";

                string rside = getValue(rraw, vars);
                result = NaviXStringEvaluator.Eval(vars[lKey], rside, oper);
            }
            else
                result = !string.IsNullOrEmpty(vars[arg]);

            return result;
        }
        private bool? evaluateIfBlock(string arg, NaviXVars vars)
        {
            Match m = multiIfTest.Match(arg);
            if (!m.Success)
                return conditionEval(arg, vars);

            bool mFlag = true;
            while (mFlag)
            {
                m = conditionExtract.Match(arg);
                if (m.Success)
                {
                    string cond = m.Groups[1].Value;
                    bool? boolObj = conditionEval(cond, vars);
                    if (boolObj == null)
                    {
                        logError("error evaluating condition {0}", cond);
                        return null;
                    }
                    if (boolObj == true)
                        arg = arg.Replace(cond, "\u0010");
                    else
                        arg = arg.Replace(cond, "\u0011");
                }
                else
                    mFlag = false;
            }
            arg = arg.Replace("\u0010", "True");
            arg = arg.Replace("\u0011", "False");
            bool result;
            if (bool.TryParse(arg, out result))
                return result;
            else
            {
                logError("error evaluating result {0}", arg);
                return null;
            }
        }
        public bool Process()
        {
            LastError = null;
            processorText = getProcessorText();
            if(string.IsNullOrEmpty(processorText))
                return false;

            //string cacheKey = OnlineVideos.Utils.EncryptLine(
            //    string.Format("{0}{1}{2}{3}",
            //        processorUrl,
            //        itemUrl,
            //        version,
            //        platform)
            //    );

            //string cacheResult = NaviXProcessorCache.Instance[cacheKey];
            //if (cacheResult != null)
            //{
            //    Data = cacheResult;
            //    logInfo("complete (from cache): final url {0}", cacheResult);
            //    return true;
            //}

            if (!processorText.StartsWith("v2"))
            {
                //TODO handle v1
                return false;
            }
            //Remove version line
            processorText = processorText.Substring(2);
            string procArgs = "";
            string instPrev = "";

            vars = new NaviXVars();
            headers = new Dictionary<string, string>();
            rep = new Dictionary<string, string>();
            ifStack = new Stack<NaviXIfBlock>();

            logDebug("nookies: ");
            foreach(NaviXNookie nookie in NaviXNookie.GetNookies(processorUrl))
            {
                string key = "nookies." + nookie.Name;
                vars[key] = nookie.Value;
                logDebug("{0}: {1}", key, nookie.Value);
            }

            int phase = 0;
            bool exitFlag = false;
            while (!exitFlag)
            {
                phase++;
                logInfo("phase {0}", phase);
                int scrape = 0;

                //reset default variables, leave user variables alone
                vars.Reset();
                rep.Clear();
                ifStack.Clear();

                //if processor args have been specified, reload processor using args
                if (!string.IsNullOrEmpty(procArgs))
                {
                    logInfo("phase {0} learn", phase);
                    processorText = WebCache.Instance.GetWebData(processorUrl + "?" + procArgs);
                    procArgs = "";
                }
                else //else set s_url to media url
                    vars["s_url"] = itemUrl;

                //reloaded processor is same as previous, endless loop
                if (processorText == instPrev)
                {
                    logError("endless loop detected");
                    LastError = "endless loop detected";
                    return false;
                }

                //keep reference to current text
                instPrev = processorText;
                vars["NIPL"] = processorText;

                //split text into individual lines
                string[] lines = processorText.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                if (lines.Length < 1)
                {
                    logError("processor has no content"); //no content
                    LastError = "processor has no content";
                    return false;
                }

                //loop through each line and process commands
                for (int x = 0; x < lines.Length; x++)
                {
                    //remove leading whitespace
                    string line = lines[x].TrimStart();
                    //check if line empty or a comment
                    if (string.IsNullOrEmpty(line) || line.StartsWith("#") || line.StartsWith("//"))
                        continue;

                    if (ifStack.Count > 0 && line != "endif" && !line.StartsWith("if "))
                    {
                        //if we are waiting for endif, continue
                        if (ifStack.Peek().IfEnd)
                            continue;
                        //else if we are waiting for next else block, continue
                        if (ifStack.Peek().IfNext && !line.StartsWith("elseif") && line != "else")
                            continue;
                    }

                    //start of else block
                    if (line == "else" && ifStack.Count > 0)
                    {
                        //if last if has been satisfied continue to next endif
                        if (ifStack.Peek().IfSatisified)
                            ifStack.Peek().IfEnd = true;
                        else //else process block contents
                            ifStack.Peek().IfNext = false;
                        continue;
                    }
                    //end of if/else blocks
                    else if (line == "endif" && ifStack.Count > 0)
                    {
                        //remove block from stack
                        ifStack.Pop();
                        continue;
                    }

                    //retrieve web data using s_url, s_cookies and any s_headers
                    //store the response and response headers and cookies
                    if (line == "scrape")
                    {
                        scrape++;
                        logDebug("Scrape {0}:", scrape);
                        if (!doScrape())
                            return false;
                    }

                    //play command, final url should be determined - stop processing and rerturn new url
                    else if (line == "play")
                    {
                        logDebug("play");
                        exitFlag = true;
                        break;
                    }

                    //report command - reload processor with specified key/values
                    else if (line == "report")
                    {
                        rep["phase"] = phase.ToString();
                        procArgs = "";
                        bool firstKey = true;
                        logDebug("report:");
                        //for each key/value
                        foreach (KeyValuePair<string, string> keyVal in rep)
                        {
                            logDebug("\t {0}: {1}", keyVal.Key, keyVal.Value);
                            string and;
                            if (!firstKey)
                                and = "&";
                            else
                            {
                                firstKey = false;
                                and = "";
                            }
                            //add arg string to proccessor args
                            if (!string.IsNullOrEmpty(keyVal.Value))
                                procArgs += string.Format("{0}{1}={2}", and, HttpUtility.UrlEncode(keyVal.Key), HttpUtility.UrlEncode(keyVal.Value));
                        }
                        break;
                    }

                    //Parse line for commmand
                    else 
                    {
                        //check if line is in recognised format
                        Match m = lParse.Match(line);
                        if (!m.Success)
                        {
                            logError("syntax error: {0}", line);
                            return false;
                        }
                        //command or variable being assigned
                        string subj = m.Groups[1].Value;
                        //args or value to assign
                        string arg = m.Groups[3].Value;

                        //start of if/elseif block
                        if (subj == "if" || subj == "elseif")
                        {
                            if (!handleIfBlock(subj, arg))
                            {
                                logError("error evaluating if statement: {0}", line);
                                return false;
                            }
                        }

                        //variable assignment
                        else if (m.Groups[2].Value == "=")
                        {
                            assignVariable(subj, arg);
                        }
                        else if (!handleCommand(line, subj, arg))
                        {
                            return false;
                        }
                    }
                }                
            }

            string url = vars["url"];            
            if (!string.IsNullOrEmpty(vars["playpath"]) || !string.IsNullOrEmpty(vars["swfplayer"]))
            {
                url += string.Format(" tcUrl={0}", vars["url"]);
                if (!string.IsNullOrEmpty(vars["app"]))
                    url += string.Format(" app={0}", vars["app"]);
                if (!string.IsNullOrEmpty(vars["playpath"]))
                    url += string.Format(" playpath={0}", vars["playpath"]);
                if (!string.IsNullOrEmpty(vars["swfplayer"]))
                    url += string.Format(" swfUrl={0}", vars["swfplayer"]);
                if (!string.IsNullOrEmpty(vars["pageurl"]))
                    url += string.Format(" pageUrl={0}", vars["pageurl"]);
                if (!string.IsNullOrEmpty(vars["swfVfy"]))
                    url += string.Format(" swfVfy={0}", vars["swfVfy"]);
            }
            
            Data = url;
            //NaviXProcessorCache.Instance[cacheKey] = url;
            logInfo("complete: final url {0}", url);
            return true;
        }
        public bool Process()
        {
            LastError     = null;
            processorText = getProcessorText();
            if (string.IsNullOrEmpty(processorText))
            {
                return(false);
            }

            //string cacheKey = OnlineVideos.Utils.EncryptLine(
            //    string.Format("{0}{1}{2}{3}",
            //        processorUrl,
            //        itemUrl,
            //        version,
            //        platform)
            //    );

            //string cacheResult = NaviXProcessorCache.Instance[cacheKey];
            //if (cacheResult != null)
            //{
            //    Data = cacheResult;
            //    logInfo("complete (from cache): final url {0}", cacheResult);
            //    return true;
            //}

            if (!processorText.StartsWith("v2"))
            {
                //TODO handle v1
                return(false);
            }
            //Remove version line
            processorText = processorText.Substring(2);
            string procArgs = "";
            string instPrev = "";

            vars    = new NaviXVars();
            headers = new Dictionary <string, string>();
            rep     = new Dictionary <string, string>();
            ifStack = new Stack <NaviXIfBlock>();

            logDebug("nookies: ");
            foreach (NaviXNookie nookie in NaviXNookie.GetNookies(processorUrl))
            {
                string key = "nookies." + nookie.Name;
                vars[key] = nookie.Value;
                logDebug("{0}: {1}", key, nookie.Value);
            }

            int  phase    = 0;
            bool exitFlag = false;

            while (!exitFlag)
            {
                phase++;
                logInfo("phase {0}", phase);
                int scrape = 0;

                //reset default variables, leave user variables alone
                vars.Reset();
                rep.Clear();
                ifStack.Clear();

                //if processor args have been specified, reload processor using args
                if (!string.IsNullOrEmpty(procArgs))
                {
                    logInfo("phase {0} learn", phase);
                    processorText = WebCache.Instance.GetWebData(processorUrl + "?" + procArgs);
                    procArgs      = "";
                }
                else //else set s_url to media url
                {
                    vars["s_url"] = itemUrl;
                }

                //reloaded processor is same as previous, endless loop
                if (processorText == instPrev)
                {
                    logError("endless loop detected");
                    LastError = "endless loop detected";
                    return(false);
                }

                //keep reference to current text
                instPrev     = processorText;
                vars["NIPL"] = processorText;

                //split text into individual lines
                string[] lines = processorText.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                if (lines.Length < 1)
                {
                    logError("processor has no content"); //no content
                    LastError = "processor has no content";
                    return(false);
                }

                //loop through each line and process commands
                for (int x = 0; x < lines.Length; x++)
                {
                    //remove leading whitespace
                    string line = lines[x].TrimStart();
                    //check if line empty or a comment
                    if (string.IsNullOrEmpty(line) || line.StartsWith("#") || line.StartsWith("//"))
                    {
                        continue;
                    }

                    if (ifStack.Count > 0 && line != "endif" && !line.StartsWith("if "))
                    {
                        //if we are waiting for endif, continue
                        if (ifStack.Peek().IfEnd)
                        {
                            continue;
                        }
                        //else if we are waiting for next else block, continue
                        if (ifStack.Peek().IfNext&& !line.StartsWith("elseif") && line != "else")
                        {
                            continue;
                        }
                    }

                    //start of else block
                    if (line == "else" && ifStack.Count > 0)
                    {
                        //if last if has been satisfied continue to next endif
                        if (ifStack.Peek().IfSatisified)
                        {
                            ifStack.Peek().IfEnd = true;
                        }
                        else //else process block contents
                        {
                            ifStack.Peek().IfNext = false;
                        }
                        continue;
                    }
                    //end of if/else blocks
                    else if (line == "endif" && ifStack.Count > 0)
                    {
                        //remove block from stack
                        ifStack.Pop();
                        continue;
                    }

                    //retrieve web data using s_url, s_cookies and any s_headers
                    //store the response and response headers and cookies
                    if (line == "scrape")
                    {
                        scrape++;
                        logDebug("Scrape {0}:", scrape);
                        if (!doScrape())
                        {
                            return(false);
                        }
                    }

                    //play command, final url should be determined - stop processing and rerturn new url
                    else if (line == "play")
                    {
                        logDebug("play");
                        exitFlag = true;
                        break;
                    }

                    //report command - reload processor with specified key/values
                    else if (line == "report")
                    {
                        rep["phase"] = phase.ToString();
                        procArgs     = "";
                        bool firstKey = true;
                        logDebug("report:");
                        //for each key/value
                        foreach (KeyValuePair <string, string> keyVal in rep)
                        {
                            logDebug("\t {0}: {1}", keyVal.Key, keyVal.Value);
                            string and;
                            if (!firstKey)
                            {
                                and = "&";
                            }
                            else
                            {
                                firstKey = false;
                                and      = "";
                            }
                            //add arg string to proccessor args
                            if (!string.IsNullOrEmpty(keyVal.Value))
                            {
                                procArgs += string.Format("{0}{1}={2}", and, HttpUtility.UrlEncode(keyVal.Key), HttpUtility.UrlEncode(keyVal.Value));
                            }
                        }
                        break;
                    }

                    //Parse line for commmand
                    else
                    {
                        //check if line is in recognised format
                        Match m = lParse.Match(line);
                        if (!m.Success)
                        {
                            logError("syntax error: {0}", line);
                            return(false);
                        }
                        //command or variable being assigned
                        string subj = m.Groups[1].Value;
                        //args or value to assign
                        string arg = m.Groups[3].Value;

                        //start of if/elseif block
                        if (subj == "if" || subj == "elseif")
                        {
                            if (!handleIfBlock(subj, arg))
                            {
                                logError("error evaluating if statement: {0}", line);
                                return(false);
                            }
                        }

                        //variable assignment
                        else if (m.Groups[2].Value == "=")
                        {
                            assignVariable(subj, arg);
                        }
                        else if (!handleCommand(line, subj, arg))
                        {
                            return(false);
                        }
                    }
                }
            }

            string url = vars["url"];

            if (!string.IsNullOrEmpty(vars["playpath"]) || !string.IsNullOrEmpty(vars["swfplayer"]))
            {
                url += string.Format(" tcUrl={0}", vars["url"]);
                if (!string.IsNullOrEmpty(vars["app"]))
                {
                    url += string.Format(" app={0}", vars["app"]);
                }
                if (!string.IsNullOrEmpty(vars["playpath"]))
                {
                    url += string.Format(" playpath={0}", vars["playpath"]);
                }
                if (!string.IsNullOrEmpty(vars["swfplayer"]))
                {
                    url += string.Format(" swfUrl={0}", vars["swfplayer"]);
                }
                if (!string.IsNullOrEmpty(vars["pageurl"]))
                {
                    url += string.Format(" pageUrl={0}", vars["pageurl"]);
                }
                if (!string.IsNullOrEmpty(vars["swfVfy"]))
                {
                    url += string.Format(" swfVfy={0}", vars["swfVfy"]);
                }
            }

            Data = url;
            //NaviXProcessorCache.Instance[cacheKey] = url;
            logInfo("complete: final url {0}", url);
            return(true);
        }