Ejemplo n.º 1
0
        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
                    {
                    }
                }
            }
        }
Ejemplo n.º 2
0
        private void ServerOnProcessRequest(object sender, HttpContextEventArgs eventArg)
        {
            HttpListenerContext context = eventArg.Context;

            try
            {
                context.Response.Headers["Server"]        = "C0D3";
                context.Response.Headers["Expires"]       = "0";
                context.Response.Headers["Cache-Control"] = "no-cache, no-store, must-revalidate";

                string applicationPath = context.Request.Url.AbsolutePath.TrimEnd('/', '\\') + '/';
                if (applicationPath.StartsWith(eventArg.Host.ApplicationPath, StringComparison.OrdinalIgnoreCase))
                {
                    applicationPath = applicationPath.Substring(eventArg.Host.ApplicationPath.Length - 1);
                }

                string[] segments = applicationPath.TrimEnd('/', '\\').Split('/', '\\');

                HttpIgnoreAttribute ignore;
                ICommand            cmd;
                bool execute = _commands.TryGetValue(context.Request.Url.AbsolutePath, out cmd);
                if (cmd == null && segments.Length == 2)
                {
                    if (_commands.TryGetValue(segments[1], out cmd))
                    {
                        execute = (!String.IsNullOrEmpty(context.Request.Url.Query) ||
                                   context.Request.HttpMethod.ToUpperInvariant() != "GET");
                    }
                }

                if (cmd != null && cmd.TryGetAttribute(out ignore))
                {
                    throw new UnauthorizedAccessException("The command is not available.");
                }
                else if (cmd != null && execute)
                {
                    ExecCommand(context, cmd);
                    return;
                }
                else if (cmd != null || (cmd == null && segments.Length == 1))
                {
                    context.Response.ContentType = "text/html; charset=utf-8";
                    using (SwitchedOutputStream output = new SwitchedOutputStream(context.Response.OutputStream, ushort.MaxValue))
                        using (StreamWriter wtr = new StreamWriter(output))
                        {
                            GenerateHtmlPage(wtr, eventArg.Host.ApplicationPath, cmd != null ? cmd.DisplayName : null);
                            if (!output.OutputSent)
                            {
                                context.Response.ContentLength64 = output.BufferPosition;
                            }
                            output.Commit();
                        }
                    return;
                }

                WriteErrorPage(context, 404, "Not Found", "The url is malformed or the command name is incorrect.");
            }
            catch (InterpreterException e)
            {
                try { WriteErrorPage(context, 400, "Bad Request", e.Message); }
                catch { }
            }
            catch (UnauthorizedAccessException e)
            {
                try { WriteErrorPage(context, 403, "Forbidden", e.Message); }
                catch { }
            }
            catch (Exception e)
            {
                try { WriteErrorPage(context, 500, "Internal Server Error", e.Message); }
                catch { }
            }
        }