private void GenerateHtmlPage(TextWriter sw, string appRoot, string itemName) { List <IDisplayInfo> items = new List <IDisplayInfo>(); if (itemName != null) { items.Add(_commands[itemName]); } else { items.AddRange(Commands); } using (XmlTextWriter w = new XmlTextWriter(sw)) { w.Formatting = System.Xml.Formatting.Indented; w.WriteStartElement("html"); w.WriteStartElement("head"); w.WriteElementString("title", Constants.ProcessName + " Help"); w.WriteEndElement(); w.WriteStartElement("body"); { HttpIgnoreAttribute ignored; if (items.Count == 1) { Command command = (Command)items[0]; HttpResponseFileAttribute resFileAttr = null; HttpRequestFileAttribute reqFileAttr = null; foreach (IArgument arg in command.Arguments) { if (reqFileAttr == null) { arg.TryGetAttribute(out reqFileAttr); } if (resFileAttr == null) { arg.TryGetAttribute(out resFileAttr); } } w.WriteElementString("h1", command.DisplayName); w.WriteElementString("p", command.Description); w.WriteStartElement("a"); w.WriteAttributeString("href", appRoot); w.WriteString("<< Back to Top"); w.WriteEndElement(); w.WriteStartElement("form"); { w.WriteAttributeString("name", command.DisplayName.ToLowerInvariant() + "Form"); if (resFileAttr == null) { w.WriteAttributeString("onsubmit", "document.getElementById('" + command.DisplayName.ToLowerInvariant() + "Submit').disabled = true;"); } w.WriteAttributeString("action", appRoot + command.DisplayName + "/"); if (reqFileAttr != null) { w.WriteAttributeString("method", "post"); w.WriteAttributeString("enctype", "multipart/form-data"); } else { w.WriteAttributeString("method", "get"); } w.WriteStartElement("ul"); w.WriteAttributeString("style", "list-style-type: none;"); w.WriteStartElement("li"); w.WriteElementString("strong", "Arguments:"); w.WriteEndElement(); foreach (Argument arg in command.Arguments) { if (arg.Visible == false || arg.Type == typeof(ICommandInterpreter)) { continue; } if (arg.IsAllArguments) { continue; } HttpHeaderBindingAttribute hdr; if (arg.TryGetAttribute(out resFileAttr) || arg.TryGetAttribute(out hdr) || arg.TryGetAttribute(out ignored)) { continue; } w.WriteStartElement("li"); w.WriteStartElement("strong"); w.WriteAttributeString("style", "display:inline-block; width: 100px; text-align: right;"); w.WriteString(arg.DisplayName); w.WriteEndElement(); w.WriteStartElement("input"); w.WriteAttributeString("name", arg.DisplayName); w.WriteAttributeString("style", "width: 300px;"); if (arg.Required) { w.WriteAttributeString("required", "required"); } if (arg.TryGetAttribute(out reqFileAttr)) { w.WriteAttributeString("type", "file"); if (reqFileAttr.AllowMultiple) { w.WriteAttributeString("multiple", "multiple"); } if (!String.IsNullOrEmpty(reqFileAttr.MimeType)) { w.WriteAttributeString("accept", reqFileAttr.MimeType); } } else { w.WriteAttributeString("type", "text"); w.WriteAttributeString("value", String.Format("{0}", arg.DefaultValue)); } w.WriteEndElement(); w.WriteString(arg.Required ? " * " : " - "); w.WriteString(arg.Description.TrimEnd('.') + "."); w.WriteEndElement(); } w.WriteStartElement("li"); w.WriteAttributeString("style", "padding-top:10px;"); { w.WriteStartElement("strong"); w.WriteAttributeString("style", "display:inline-block; width: 100px; text-align: right;"); w.WriteString(" "); w.WriteEndElement(); w.WriteStartElement("input"); w.WriteAttributeString("id", command.DisplayName.ToLowerInvariant() + "Submit"); w.WriteAttributeString("name", command.DisplayName.ToLowerInvariant() + "Submit"); w.WriteAttributeString("type", "submit"); w.WriteAttributeString("value", command.DisplayName); w.WriteEndElement(); } w.WriteEndElement(); w.WriteEndElement(); } w.WriteEndElement(); } else { w.WriteElementString("h1", Constants.ProductName + " " + Constants.ProductVersion); w.WriteElementString("p", System.Diagnostics.FileVersionInfo.GetVersionInfo(Constants.ProcessFile).Comments); Dictionary <string, List <IDisplayInfo> > all = new Dictionary <string, List <IDisplayInfo> >(StringComparer.OrdinalIgnoreCase); foreach (IDisplayInfo item in items) { if (item.ReflectedType == typeof(CommandInterpreter) || item.ReflectedType == typeof(BuiltInCommands.BuiltIn)) { continue; } if (item.TryGetAttribute(out ignored)) { continue; } List <IDisplayInfo> l; if (!all.TryGetValue(item.Category, out l)) { all.Add(item.Category, l = new List <IDisplayInfo>()); } l.Add(item); } List <string> keys = new List <string>(all.Keys); keys.Sort(); foreach (string key in keys) { List <IDisplayInfo> list = all[key]; w.WriteElementString("h2", key + ":"); foreach (IDisplayInfo info in list) { ICommand command = info as ICommand; if (command == null || !info.Visible) { continue; } w.WriteStartElement("li"); w.WriteStartElement("a"); w.WriteAttributeString("href", appRoot + command.DisplayName + '/'); w.WriteElementString("b", command.DisplayName); w.WriteEndElement(); w.WriteString(" - "); w.WriteString(info.Description.TrimEnd('.') + "."); w.WriteEndElement(); } } } } foreach (AssemblyCopyrightAttribute copy in Constants.EntryAssembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), true)) { w.WriteElementString("p", copy.Copyright); } w.WriteEndElement(); w.WriteEndElement(); w.Flush(); } }
private void ExecCommand(HttpListenerContext context, ICommand cmd) { TextWriter stdOut; TextWriter stdErr = new StringWriter(); string tempdir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N").Substring(0, 16)); SwitchedOutputStream output = new SwitchedOutputStream(context.Response.OutputStream, ushort.MaxValue); try { string contentType = "text/plain"; IArgument reqFile = null; IArgument resFile = null; foreach (IArgument argument in cmd.Arguments) { HttpRequestFileAttribute reqFileAttr = null; HttpResponseFileAttribute resFileAttr = null; if (argument.TryGetAttribute(out reqFileAttr)) { Check.Assert <ArgumentException>(null == Interlocked.Exchange(ref reqFile, argument)); } if (argument.TryGetAttribute(out resFileAttr)) { Check.Assert <ArgumentException>(null == Interlocked.Exchange(ref resFile, argument)); } } if (reqFile != null && reqFile.Required && ( context.Request.HttpMethod.ToUpperInvariant() != "POST" || !context.Request.ContentType.StartsWith( "multipart/form-data", StringComparison.OrdinalIgnoreCase))) { throw new InvalidOperationException(); } List <string> args = new List <string>(); args.Add(cmd.DisplayName); HttpResponseTypeAttribute ctypeAttr; if (cmd.TryGetAttribute(out ctypeAttr) && !String.IsNullOrEmpty(ctypeAttr.MimeType)) { contentType = ctypeAttr.MimeType; } GetArguments(context, cmd, tempdir, ref contentType, args); if (resFile != null) { HttpResponseFileAttribute fattr; resFile.TryGetAttribute(out fattr); Directory.CreateDirectory(tempdir); string tempPath = Path.Combine(tempdir, cmd.DisplayName + fattr.Extension); args.Add(String.Format("/{0}={1}", resFile.DisplayName, tempPath)); using (stdOut = new StreamWriter(output, Encoding.UTF8)) Run(args.ToArray(), stdOut, stdErr, TextReader.Null); if (output.OutputSent) { throw new ApplicationException("Headers already sent."); } context.Response.ContentType = fattr.MimeType ?? "application/binary"; context.Response.Headers.Add("Content-Disposition", String.Format("attachment; filename=\"{0}{1}\"", cmd.DisplayName, fattr.Extension)); using (Stream ostream = context.Response.OutputStream) using (Stream istream = new FileStream(tempPath, FileMode.Open, FileAccess.Read, FileShare.None)) { int len; byte[] buffer = new byte[ushort.MaxValue]; while (0 != (len = istream.Read(buffer, 0, buffer.Length))) { ostream.Write(buffer, 0, len); } } } else { context.Response.ContentType = contentType + (contentType.Contains("text") || contentType.Contains("xml") || contentType.Contains("json") ? "; charset=utf-8" : ""); using (stdOut = new StreamWriter(output, Encoding.UTF8)) Run(args.ToArray(), stdOut, stdErr, TextReader.Null); } if (!output.OutputSent) { context.Response.ContentLength64 = output.BufferPosition; } output.Commit(); } catch (InterpreterException) { throw; } catch (Exception e) { if (output.OutputSent) { using (stdOut = new StreamWriter(output, Encoding.UTF8)) { stdOut.Write("EXCEPTION: "); stdOut.WriteLine(e.Message); stdOut.WriteLine(stdErr.ToString()); } output.Commit(); } else { WriteErrorPage(context, 500, "Internal Server Error", e.Message, stdErr.ToString(), output.ToString()); } } finally { if (Directory.Exists(tempdir)) { try { Directory.Delete(tempdir, true); } catch { } } } }