/// <summary> /// Creates a Javascript execution environment /// </summary> /// <param name="fileContainer">The object that will be accessed through Javascript</param> /// <param name="javascriptContainer">The text file that contains the javascript</param> public ExecutionEnvironment( FileHandlerFactoryLocator fileHandlerFactoryLocator, IFileContainer javascriptContainer, IFileContainer fileContainer, SubProcess subProcess, ParentScope parentScope) { _FileHandlerFactoryLocator = fileHandlerFactoryLocator; _JavascriptContainer = javascriptContainer; _JavascriptLastModified = javascriptContainer.LastModified; parentScope.WebHandlersWithThisAsParent.Enqueue(fileContainer.WebHandler); object toDiscard; ISession ownerSession = FileHandlerFactoryLocator.SessionManagerHandler.CreateSession(); try { if (null != fileContainer.Owner) ownerSession.Login(fileContainer.Owner); IWebConnection ownerWebConnection = new BlockingShellWebConnection( FileHandlerFactoryLocator.WebServer, ownerSession, fileContainer.FullPath, null, null, new CookiesFromBrowser(), CallingFrom.Web, WebMethod.GET); ScopeWrapper = new ScopeWrapper( fileHandlerFactoryLocator, subProcess, fileContainer, parentScope, ownerWebConnection, out toDiscard); } catch (Exception e) { // If the Javascript has an error in it, it must be ignored. If an error were returned, then malformed Javascript could hose the system! this._ExecutionEnvironmentErrors = e.ToString(); log.Error("Error creating scope", e); } finally { FileHandlerFactoryLocator.SessionManagerHandler.EndSession(ownerSession.SessionId); } }
/// <summary> /// Returns all of the script IDs for the class /// </summary> /// <param name="javascriptClass">The text handler that has the class's javascript</param> /// <param name="subProcess">The process that must have the given script loaded</param> /// <returns></returns> public ScopeInfo GetScopeInfoForClass(ITextHandler javascriptClass, SubProcess subProcess) { DateTime javascriptLastModified = javascriptClass.FileContainer.LastModified; ScopeInfo toReturn = null; using (TimedLock.Lock(ScopeInfoCache)) ScopeInfoCache.TryGetValue(javascriptClass.FileContainer.FileId, out toReturn); if (null != toReturn) if (toReturn.JavascriptLastModified == javascriptLastModified) { using (TimedLock.Lock(PrecompiledScriptDataByID)) foreach (int scriptID in toReturn.ScriptsAndIDsToBuildScope) subProcess.LoadCompiled( Thread.CurrentThread.ManagedThreadId, PrecompiledScriptDataByID[scriptID], scriptID); return toReturn; } string javascript = javascriptClass.ReadAll(); string fileType = null; List<int> scriptIDsToBuildScope = new List<int>(); ISession ownerSession = FileHandlerFactoryLocator.SessionManagerHandler.CreateSession(); try { ownerSession.Login(javascriptClass.FileContainer.Owner); IWebConnection ownerWebConnection = new BlockingShellWebConnection( FileHandlerFactoryLocator.WebServer, ownerSession, javascriptClass.FileContainer.FullPath, null, null, new CookiesFromBrowser(), CallingFrom.Web, WebMethod.GET); IEnumerable<ScriptAndMD5> dependantScriptsAndMD5s = FileHandlerFactoryLocator.WebServer.WebComponentResolver.DetermineDependantScripts( GetRequiredScriptURLs(javascriptClass, out fileType), ownerWebConnection); // Load static methods that are passed into the Javascript environment as-is Dictionary<string, MethodInfo> functionsInScope = SubProcessFactory.GetFunctionsForFileType(fileType); // Load all dependant scripts foreach (ScriptAndMD5 dependantScript in dependantScriptsAndMD5s) { int scriptID = GetScriptID( dependantScript.ScriptName + "___" + ownerSession.User.Identity, dependantScript.MD5, dependantScript.Script, subProcess); scriptIDsToBuildScope.Add(scriptID); } // Construct Javascript to shell to the "base" webHandler Set<Type> webHandlerTypes = new Set<Type>(FileHandlerFactoryLocator.WebHandlerPlugins); if (null != fileType) webHandlerTypes.Add(FileHandlerFactoryLocator.WebHandlerClasses[fileType]); string baseWrapper = GetJavascriptWrapperForBase("base", webHandlerTypes); scriptIDsToBuildScope.Add( GetScriptID( javascriptClass.FileContainer.FullPath + "___" + "serversideBaseWrapper", StringParser.GenerateMD5String(baseWrapper), baseWrapper, subProcess)); // Get the ID for the actual javascript scriptIDsToBuildScope.Add( GetScriptID( javascriptClass.FileContainer.FullPath, StringParser.GenerateMD5String(javascript), javascript, subProcess)); // Add a little shunt to return information about the options scriptIDsToBuildScope.Add( GetScriptID( "____scopeshunt", "xxx", "\nif (this.options) options; else null;", subProcess)); toReturn = new ScopeInfo( javascriptLastModified, functionsInScope, scriptIDsToBuildScope); using (TimedLock.Lock(ScopeInfoCache)) ScopeInfoCache[javascriptClass.FileContainer.FileId] = toReturn; return toReturn; } finally { FileHandlerFactoryLocator.SessionManagerHandler.EndSession(ownerSession.SessionId); } }
private ParentScope CreateParentScope(IFileContainer javascriptContainer) { List<string> scriptsToEval = new List<string>(); List<string> requestedScripts = new List<string>(new string[] { "/API/AJAX_serverside.js", "/API/json2.js" }); string fileType = null; StringBuilder javascriptBuilder = new StringBuilder(); foreach (string line in javascriptContainer.CastFileHandler<ITextHandler>().ReadLines()) { // find file type if (line.Trim().StartsWith("// FileType:")) fileType = line.Substring(12).Trim(); // Find dependant scripts else if (line.Trim().StartsWith("// Scripts:")) foreach (string script in line.Substring(11).Split(',')) requestedScripts.Add(script.Trim()); else javascriptBuilder.AppendFormat("{0}\n", line); } string javascript = javascriptBuilder.ToString(); Dictionary<string, MethodInfo> functionsInScope = new Dictionary<string, MethodInfo>(); List<KeyValuePair<IFileContainer, DateTime>> loadedScriptsModifiedTimes = new List<KeyValuePair<IFileContainer, DateTime>>(); ISession ownerSession = FileHandlerFactoryLocator.SessionManagerHandler.CreateSession(); try { ownerSession.Login(javascriptContainer.Owner); IWebConnection ownerWebConnection = new BlockingShellWebConnection( FileHandlerFactoryLocator.WebServer, ownerSession, javascriptContainer.FullPath, null, null, new CookiesFromBrowser(), CallingFrom.Web, WebMethod.GET); IEnumerable<ScriptAndMD5> dependantScriptsAndMD5s = FileHandlerFactoryLocator.WebServer.WebComponentResolver.DetermineDependantScripts( requestedScripts, ownerWebConnection); // Load static methods that are passed into the Javascript environment as-is foreach (Type javascriptFunctionsType in GetTypesThatHaveJavascriptFunctions(fileType)) foreach (MethodInfo method in javascriptFunctionsType.GetMethods(BindingFlags.Static | BindingFlags.Public)) functionsInScope[method.Name] = method; // Load all dependant scripts foreach (ScriptAndMD5 dependantScript in dependantScriptsAndMD5s) { string scriptName = dependantScript.ScriptName; if (scriptName.Contains("?")) scriptsToEval.Add(ownerWebConnection.ShellTo(scriptName).ResultsAsString); else { IFileContainer scriptFileContainer = FileHandlerFactoryLocator.FileSystemResolver.ResolveFile(scriptName); if (scriptFileContainer.FileHandler is ITextHandler) { loadedScriptsModifiedTimes.Add(new KeyValuePair<IFileContainer, DateTime>(scriptFileContainer, scriptFileContainer.LastModified)); scriptsToEval.Add(scriptFileContainer.CastFileHandler<ITextHandler>().ReadAll()); } else scriptsToEval.Add(ownerWebConnection.ShellTo(scriptName).ResultsAsString); } } loadedScriptsModifiedTimes.Add(new KeyValuePair<IFileContainer, DateTime>(javascriptContainer, javascriptContainer.LastModified)); // Construct Javascript to shell to the "base" webHandler HashSet<Type> webHandlerTypes = new HashSet<Type>(FileHandlerFactoryLocator.WebHandlerPlugins); if (null != fileType) webHandlerTypes.Add(FileHandlerFactoryLocator.WebHandlerClasses[fileType]); string baseWrapper = GetJavascriptWrapperForBase("base", webHandlerTypes); scriptsToEval.Add(baseWrapper); scriptsToEval.Add(javascript); scriptsToEval.Add("if (this.options) options; else null;"); ParentScope parentScope = new ParentScope(loadedScriptsModifiedTimes, functionsInScope); Dictionary<string, object> data = new Dictionary<string, object>(); data["Scripts"] = scriptsToEval; data["Functions"] = functionsInScope.Keys; _SubProcess.CreateParentScope(parentScope.ParentScopeId, Thread.CurrentThread.ManagedThreadId, data); return parentScope; } finally { FileHandlerFactoryLocator.SessionManagerHandler.EndSession(ownerSession.SessionId); } }
/// <summary> /// Establishes trust between a user and another server /// </summary> /// <param name="sender"></param> /// <param name="receiveNotificationEndpoint"></param> /// <param name="callback"></param> private void BeginEstablishTrust( IUserOrGroup sender, string receiveNotificationEndpoint, string establishTrustEndpoint, Action<string> callback, Action<Exception> errorCallback) { // Make sure the timer is created if (null == EstablishTrustDataTimer) { Timer timer = new Timer(EstablishTrustDataCleanup, null, 600000, 600000); if (null != Interlocked.CompareExchange<Timer>(ref EstablishTrustDataTimer, timer, null)) timer.Dispose(); } // Get the avatar byte[] avatar; ISession session = FileHandlerFactoryLocator.SessionManagerHandler.CreateSession(); try { IWebConnection webConnection = new BlockingShellWebConnection( FileHandlerFactoryLocator.WebServer, session, "/Users/" + sender.Name + ".user?Method=GetAvatar", null, null, null, CallingFrom.Web, WebMethod.GET); IWebResults webResults = webConnection.ShellTo("/Users/" + sender.Name + ".user?Method=GetAvatar"); using (Stream stream = webResults.ResultsAsStream) { avatar = new byte[stream.Length]; stream.Read(avatar, 0, avatar.Length); } } finally { FileHandlerFactoryLocator.SessionManagerHandler.EndSession(session.SessionId); } // Hold on to callback information for use after trust is established string token; using (TimedLock.Lock(EstablishTrustDatasByToken)) { do token = Convert.ToBase64String(SRandom.NextBytes(100)); while (EstablishTrustDatasByToken.ContainsKey(token)); EstablishTrustDatasByToken[token] = new EstablishTrustData(); } HttpWebClient httpWebClient = new HttpWebClient(); httpWebClient.BeginPost( establishTrustEndpoint, delegate(HttpResponseHandler httpResponseHandler) { if (httpResponseHandler.StatusCode == System.Net.HttpStatusCode.Created) { string senderToken; using (TimedLock.Lock(EstablishTrustDatasByToken)) { senderToken = EstablishTrustDatasByToken[token].SenderToken; EstablishTrustDatasByToken.Remove(token); } this.persistedUserManagerData.Write(userManagerData => { var user = userManagerData.GetUser(sender.Id); string oldSenderToken; if (user.receiveNotificationSenderTokensByEndpoint.TryGetValue(receiveNotificationEndpoint, out oldSenderToken)) user.receiveNotificationEndpointsBySenderToken.Remove(oldSenderToken); user.receiveNotificationEndpointsBySenderToken[senderToken] = receiveNotificationEndpoint; user.receiveNotificationSenderTokensByEndpoint[receiveNotificationEndpoint] = senderToken; }); callback(senderToken); } else errorCallback(new ParticleException.CouldNotEstablishTrust("Couldn't establish trust: " + httpResponseHandler.AsString())); }, errorCallback, new KeyValuePair<string, string>("senderIdentity", sender.Identity), new KeyValuePair<string, string>("token", token), new KeyValuePair<string, string>("avatar", Convert.ToBase64String(avatar)), new KeyValuePair<string, string>("loginURL", string.Format("http://{0}/Users/UserDB?Method=OpenIDLogin", FileHandlerFactoryLocator.HostnameAndPort)), new KeyValuePair<string, string>("loginURLOpenID", "openid_url"), new KeyValuePair<string, string>("loginURLWebFinger", "openid_url"), new KeyValuePair<string, string>("loginURLRedirect", "redirect"), GenerateSecurityTimestamp()); }
public IWebResults ShellTo(WebMethod method, string url, byte[] content, string contentType, CallingFrom callingFrom, bool bypassJavascript) { ShellWebConnection shellWebConnection = new BlockingShellWebConnection( this, method, url, content, contentType, _CookiesFromBrowser, callingFrom); shellWebConnection._BypassJavascript = bypassJavascript; return shellWebConnection.GenerateResultsForClient(); }
public IWebResults ShellTo(string url, CallingFrom callingFrom, bool bypassJavascript) { ShellWebConnection shellWebConnection = new BlockingShellWebConnection( url, this, PostParameters, _CookiesFromBrowser, callingFrom); shellWebConnection._BypassJavascript = bypassJavascript; return shellWebConnection.GenerateResultsForClient(); }
public IWebResults ShellTo(string url, IUser user) { ISession shellSession = new ShellSession(Session, user); ShellWebConnection shellWebConnection = new BlockingShellWebConnection( WebServer, shellSession, url, new byte[0], ContentType, CookiesFromBrowser, CallingFrom, WebMethod.GET); shellWebConnection._BypassJavascript = BypassJavascript; return shellWebConnection.GenerateResultsForClient(); }
public IWebConnection CreateShellConnection(IUser user) { ISession shellSession = new ShellSession(Session, user); ShellWebConnection shellWebConnection = new BlockingShellWebConnection( this, shellSession, RequestedFile, GetParameters, new byte[0], ContentType, CookiesFromBrowser, CallingFrom); shellWebConnection._BypassJavascript = BypassJavascript; return shellWebConnection; }
private void LoadComponent( ITemplateParsingState templateParsingState, IDictionary<string, object> getParameters, XmlElement element) { XmlAttribute srcAttribute = (XmlAttribute)element.Attributes.GetNamedItem("src", templateParsingState.TemplateHandlerLocator.TemplatingConstants.TemplateNamespace); XmlAttribute urlAttribute = (XmlAttribute)element.Attributes.GetNamedItem("url", templateParsingState.TemplateHandlerLocator.TemplatingConstants.TemplateNamespace); // handle GET parameters // First, handle oc:getpassthrough IDictionary<string, object> myGetParameters; XmlAttribute getpassthroughAttribute = (XmlAttribute)element.Attributes.GetNamedItem("getpassthough", templateParsingState.TemplateHandlerLocator.TemplatingConstants.TemplateNamespace); if (null == getpassthroughAttribute) { myGetParameters = DictionaryFunctions.Create<string, object>(getParameters); myGetParameters.Remove("Method"); myGetParameters.Remove("Action"); } else { if ("false" == getpassthroughAttribute.Value) myGetParameters = new Dictionary<string, object>(); else { myGetParameters = DictionaryFunctions.Create<string, object>(getParameters); myGetParameters.Remove("Method"); myGetParameters.Remove("Action"); } } // Next, pull out get parameters from the tag foreach (XmlAttribute attribute in element.Attributes) if ("" == attribute.NamespaceURI) myGetParameters[attribute.LocalName] = attribute.Value; if ((null == srcAttribute) && (null == urlAttribute)) // Remove empty components element.ParentNode.RemoveChild(element); else if ((null != srcAttribute) && (null != urlAttribute)) templateParsingState.ReplaceNodes( element, templateParsingState.GenerateWarningNode("Either oc:src or oc:url can be specified; you can not choose both: " + element.OuterXml)); else if (null != srcAttribute) { string fileName = templateParsingState.FileHandlerFactoryLocator.FileSystemResolver.GetAbsolutePath( templateParsingState.GetCWD(element), srcAttribute.Value); IFileContainer fileContainer; try { fileContainer = templateParsingState.FileHandlerFactoryLocator.FileSystemResolver.ResolveFile(fileName); } catch (FileDoesNotExist fdne) { log.Warn("An attempt was made to use a non-existant file in a template", fdne); templateParsingState.ReplaceNodes( element, templateParsingState.GenerateWarningNode(fileName + " not found")); return; } templateParsingState.WebConnection.TouchedFiles.Add(fileContainer); // If the user doesn't have permission for the component and the component has something to use instead, use it if (null == fileContainer.LoadPermission(templateParsingState.WebConnection.Session.User.Id) && element.HasChildNodes) { XmlNode replacement = element.OwnerDocument.CreateElement("div"); foreach (XmlNode errorNode in element.ChildNodes) replacement.AppendChild(errorNode); element.ParentNode.InsertAfter(replacement, element); element.ParentNode.RemoveChild(element); } else { // If the user has permission, resolve the component and deal with default errors XmlDocument componentDocument; // TODO: GET Parameters try { componentDocument = templateParsingState.LoadXmlDocumentAndReplaceGetParameters( myGetParameters, fileContainer, templateParsingState.GetXmlParseMode(element)); XmlNode firstChild = componentDocument.FirstChild; XmlNodeList replacementNodes; if ((firstChild.LocalName == "componentdef") && (firstChild.NamespaceURI == templateParsingState.TemplateHandlerLocator.TemplatingConstants.TemplateNamespace)) replacementNodes = firstChild.ChildNodes; else replacementNodes = componentDocument.ChildNodes; templateParsingState.SetCWD(replacementNodes, fileContainer.ParentDirectoryHandler.FileContainer.FullPath); templateParsingState.ReplaceNodes(element, replacementNodes); } catch (WebResultsOverrideException wroe) { templateParsingState.ReplaceNodes( element, templateParsingState.GenerateWarningNode(wroe.WebResults.ResultsAsString)); } catch (Exception e) { log.Error("An error occured when loading a component", e); templateParsingState.ReplaceNodes( element, templateParsingState.GenerateWarningNode("An unhandled error occured. See the system logs for more information")); } } } else if (null != urlAttribute) { XmlNode resultNode; string url = urlAttribute.Value; foreach (KeyValuePair<string, object> getParameter in myGetParameters) url = HTTPStringFunctions.AppendGetParameter(url, getParameter.Key, getParameter.Value.ToString()); try { if (url.StartsWith("https://")) resultNode = templateParsingState.GenerateWarningNode("https component nodes aren't supported due to certificate complexities"); else if (url.StartsWith("http://")) { HttpResponseHandler httpResponse = templateParsingState.WebConnection.Session.HttpWebClient.Get(url); if ("text/xml" == httpResponse.ContentType) resultNode = templateParsingState.LoadXmlDocument("<html xmlns=\"" + templateParsingState.TemplateHandlerLocator.TemplatingConstants.HtmlNamespace + "\"><head></head><body>" + httpResponse.AsString() + "</body></html>", XmlParseMode.Xml, templateParsingState.GetCWD(element)).FirstChild.ChildNodes[1]; else resultNode = element.OwnerDocument.CreateTextNode(httpResponse.AsString()); } else try { ShellWebConnection shellWebConnection = new BlockingShellWebConnection( url, templateParsingState.WebConnection, null, templateParsingState.WebConnection.CookiesFromBrowser); IWebResults shellResults = shellWebConnection.GenerateResultsForClient(); if ("text/xml" == shellResults.ContentType) resultNode = templateParsingState.LoadXmlDocument("<html xmlns=\"" + templateParsingState.TemplateHandlerLocator.TemplatingConstants.HtmlNamespace + "\"><head></head><body>" + shellResults.ResultsAsString + "</body></html>", XmlParseMode.Xml, templateParsingState.GetCWD( element)).FirstChild.ChildNodes[1]; else resultNode = element.OwnerDocument.CreateTextNode(shellResults.ResultsAsString); } catch (WebResultsOverrideException wroe) { resultNode = templateParsingState.GenerateWarningNode(wroe.WebResults.ResultsAsString); } } catch (Exception e) { log.Error("An error occured when loading a component", e); resultNode = templateParsingState.GenerateWarningNode("An unhandled error occured. See the system logs for more information"); } templateParsingState.ReplaceNodes(element, resultNode); } }
/// <summary> /// Evaluates the specified template /// </summary> /// <param name="template"></param> /// <param name="arguments"></param> /// <returns></returns> public static IWebResults evaluateTemplate(string template, Dictionary<string, object> arguments) { if (null == template) template = "/DefaultTemplate/headerfooter.ochf"; FunctionCallContext functionCallContext = FunctionCallContext.GetCurrentContext(); IFileContainer templateEngineFileContainer = functionCallContext.ScopeWrapper.FileHandlerFactoryLocator.FileSystemResolver.ResolveFile("/System/TemplateEngine"); ITemplateEngine templateEngineWebHandler = (ITemplateEngine)templateEngineFileContainer.WebHandler; RequestParameters requestParameters = new RequestParameters(); if (null != arguments) foreach (KeyValuePair<string, object> requestParameter in (Dictionary<string, object>)arguments) requestParameters.Add(requestParameter.Key, requestParameter.Value.ToString()); IWebConnection webConnection = new BlockingShellWebConnection( functionCallContext.WebConnection, functionCallContext.WebConnection.Session, template, requestParameters, null, null, functionCallContext.WebConnection.CookiesFromBrowser, FunctionCaller.CallingFrom); return templateEngineWebHandler.Evaluate(webConnection, template); }