Tuesday, May 28, 2013

jitjot.net alpha release

jitjot.net is an online platform where you can read, write, run, and share .NET code directly in your browser.  Unlike many online editors, the goal of jitjot is multifaceted; instead of attempting to focus on the task of emulating all of a desktop IDE's features, our goal is to provide a tool that will supplement your development process, not replace it!  The feature set of jitjot at it's current stage is, although functional, minimal, and is only a limited subset of the potential we envision for the site.

At the basic level, jitjot is a code scratchpad.  You can insert your own code on the site, run it, and see the results in your browser; probably not the first time you've seen a site that can do this.

jitjot will inspect your code when built, and generate a list of methods and their corresponding parameters for you to pass arguments to, if any.  You can then run your code, and the output is shown on two panels - one for showing console output and one for displaying data returned by the method being called.  Simple enough.
passing arguments to code


Arguments passed to and returned from your code are in JSON format.  Simple types such as integers and strings are passed around verbatim as you type them or as they are returned from your code; types such as classes with properties are translated to and from JSON format.  This means if one of your parameters is an array of some type - lets say an int[] - then the argument you pass in would be a JSON array containing a set of integers.  It also means that if your code returns a value, that data in that return value will be translated to its JSON equivalent then served to you.

output
Your code has access to basic resources including writing to the console and networking.  This means you can write code that acts as a proxy between you and an endpoint.  Combined with the JSON format that data is returned as, you can write code that aggregates data from multiple points, create
API mashups, etc.  You can also write to the console in case data returned from your method is not enough.


HTTP GET of reddit.com + writing HTML to console
You can also upload custom references and use them in your code.  If there is a library that you want to test out or need to use in your code, no problem!  Just upload it in the reference editor and it will be included when you compile and run your code.


After saving code, you can call methods directly via an HTTP GET request on that code, passing in arguments as URL parameters, and use that output wherever you have access to the service.  For example, we could write a snippet of code that retrieves an XML document, parses it, and returns a subset of the data.

This is a basic overview of the sites features that are currently implemented.  Since it is in such an early stage of development, feedback is key!  If you find any issues, security related or otherwise, or just want to leave an opinion on what YOU think would be interesting to see, don't hesitate to contact us; we are eager to receive your feedback.  The site is not perfect and there will be bugs - otherwise known as features in hindsight - 

Our short-term goals for jitjot include:

* F# support
* Adding references to other jitjot projects
* An output window that can be easily embedded in other websites.

If you have any questions on the syntax for passing arguments to code, visit: http://jitjot.net/help
You must be registered on the site to save or clone code.
Mobile devices are not supported at this time.

Oh, any by the way, https://jitjot.net

Tuesday, December 11, 2012

Sandboxing managed code with an AppDomain

Sandboxing is a technique used to restrict the resources that an application can access and is generally used to run untrusted code.

An example of a sandboxed environment is a Virtual Machine (VM), which hosts an entire operating system; this is useful for running untrusted code, but can be a bit too much overhead when, instead of needing to sandbox the entire operating system, we only need to sandbox a runtime or a single application.  Fortunately, .NET does let us place restrictions on processes in the form of an AppDomain.


Microsoft's definition of an AppDomain is "an isolated environment where applications execute".  Perfect.  Now how do we work with it?

First, let's define a use-case for creating a sandbox and we'll go from there.

Imagine that you are writing an application that loads plugins written in C# .  These plugins have access to the same resources that the hosting application does, but that is a bit too control much considering that the plugin:

* Is untrusted
* Has access to the registry
* Has full access to the file system
* Has access to network resources
* etc.

Now, lets imagine that the hosting application needs and utilizes all of these resources and the purpose of each plugin is only to run a calculation and display output from that to an output stream.  It can access only the files that it has created and must be completely isolated from other plugins and their data.

So, we need to ensure that each plugin has restrictions on the files it can access.  In short, each plugin must:

* Only be able to access a directory assigned to the process
* Be able to only modify files inside that directory
* Not be able to access files created by other plugins
* Be denied all other resources aside from limited filesystem access.

We also need to take into account that since each plugin is untrusted, we need to set boundaries on memory and hard disk IO.  We cannot have this plugin consume excessive memory and we need to ensure that the application can't consume all of our disk space maliciously.  Fortunately, there exists a Win32 method for doing this called Job Objects.  To access these in C#, you will need to use a bit of P/Invoke to utilize this feature, but it's not very difficult to say the least.

Combining these two ideas, one should be able to place limits on I/O as well as virtual memory usage.  I recently began working on a simple library to combine these two into a unified basic sandbox process with time being the only thing holding back a release.  I will share whatever code I can when I get the opportunity to do so, preferrably in the form of a usable API.

Saturday, December 8, 2012

Basic HttpClient class

So, I do a lot of web scraping - work fit for an episode of Dirty Jobs I'd say - and I end up writing a lot of code to do this.  Standard toolkit includes HtmlAgilityPack for HTML parsing, Fiddler for monitoring network traffic, Firebug for both, HttpWeb(Request|Response) (System.NET), and a web scraping library that I wrote to simplify my life, modifying the code as needed.

So, here's a bare-bones version of a basic HttpWebClient that stores cookies for authenticating, sessions, and stuff - an except of the library I use  Obviously doesn't process Javascript or deal with Javascript-set cookies, have fun with those.  Uses C# 5 async keyword, so .NET 4.5 is required.


Code:
public class HttpWebClient
{
    public WebProxy WebProxy { get; set; }
    public CookieContainer CookieContainer { get; set; }

    private readonly int _timeoutMilliseconds;

    static HttpWebClient()
    {
        ServicePointManager.UseNagleAlgorithm = true;
        ServicePointManager.MaxServicePoints = 500;
        ServicePointManager.DefaultConnectionLimit = 500;
        ServicePointManager.Expect100Continue = false;
    }

    // Default to 30 second timeout
    public HttpWebClient(WebProxy proxy = null, int timeoutMilliseconds = 30000)
    {
        this.WebProxy = proxy;
        this.CookieContainer = new CookieContainer();

        _timeoutMilliseconds = timeoutMilliseconds;
    }

    public async Task<HttpWebResponse> HttpGet(string url)
    {
        var request = ConstructHttpGetRequest(url);
        return await GetHttpResponse(request);
    }

    public async Task<HttpWebResponse> HttpPost(string url, string postData)
    {
        var request = ConstructHttpPostRequest(url, postData);
        return await GetHttpResponse(request);
    }

    public async Task<HttpWebResponse> HttpPost(string url, Dictionary<string, string> valueDictionary)
    {
        var postData = GeneratePostBody(valueDictionary);
        var request = ConstructHttpPostRequest(url, postData);
        return await GetHttpResponse(request);
    }

    public HttpWebRequest ConstructHttpGetRequest(string url)
    {
        return CreateDefaultHttpWebRequest(url, "GET");
    }

    public HttpWebRequest ConstructHttpPostRequest(string url, Dictionary<string, string> valueDictionary, string host = null)
    {
        var postData = GeneratePostBody(valueDictionary);
        return ConstructHttpPostRequest(url, postData);
    }

    public HttpWebRequest ConstructHttpPostRequest(string url, string postData)
    {
        var request = CreateDefaultHttpWebRequest(url, "POST");
        WriteToHttpWebRequestStream(request, postData);
        return request;
    }

    protected void WriteToHttpWebRequestStream(HttpWebRequest httpWebRequest, string data)
    {
        WriteToHttpWebRequestStream(httpWebRequest, Encoding.ASCII.GetBytes(data));
    }

    protected void WriteToHttpWebRequestStream(HttpWebRequest httpWebRequest, byte[] data)
    {
        using (var requestStream = httpWebRequest.GetRequestStream())
        {
            var contentBytes = data;
            requestStream.Write(contentBytes, 0, contentBytes.Length);
        }
    }

    protected HttpWebRequest CreateDefaultHttpWebRequest(string url, string method, string accept=null)
    {
        var request = (HttpWebRequest)WebRequest.Create(url);

        // Default to HTTP 1.0
        request.ProtocolVersion = HttpVersion.Version10;

        request.Timeout = _timeoutMilliseconds;
        request.Host = new Uri(url).Host;
        request.CookieContainer = CookieContainer;
        request.Method = method;
        request.Accept = "application/json,text/javascript,text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        request.ContentType = "application/x-www-form-urlencoded";
        request.Headers["Accept-Charset"] = "ISO-8859-1,utf-8;q=0.7,*;q=0.7";
            
        if(this.WebProxy != null)
            request.Proxy = this.WebProxy;

        return request;
    }

    public async Task<HttpWebResponse> GetHttpResponse(HttpWebRequest request)
    {
        HttpWebResponse response = await Task<HttpWebResponse>.Factory.FromAsync(request.BeginGetResponse, r => (HttpWebResponse) request.EndGetResponse(r), null);
        return response;
    }
        
    public void ClearSession()
    {
        if(CookieContainer != null)
            CookieContainer = new CookieContainer();
    }

    public static string GeneratePostBody(Dictionary<string, string> postValues)
    {
        var values = String.Join("&", postValues.Select(kv => String.Join("=", kv.Key, kv.Value)));
        return values;
    }
}   


On top of this basic class, you can build APIs for various websites and HTTP services.  Nothing fancy at all, just saves a bit of typing.  Change whatever properties you need and enjoy!

Thursday, May 10, 2012

Using Dropbox as a free source code repository

So, I'm not sure why I didn't think of this sooner, but, it turns out that you can use Dropbox, which comes with 2GB of free storage space, to version your projects (GIT, SVN, etc.).

I found a nice tutorial for doing this using Visual Studio and Git Extensions at the following address:
http://www.remondo.net/git-source-control-for-visual-studio-2010-on-dropbox/

Definitely useful and something to keep in mind for personal projects and such.

Friday, April 20, 2012

CodeMirror Rendering Issues

So, I was having a very, very annoying problem with CodeMirror where the editor would leak outside of the bounds it was given, causing the text to be outside of the CodeMirror div.  Typing into the editor would cause the editor to resize to ridiculous size (10000px +) with each character typed into it.  So, turns out, I was simply missing a reference to the codemirror.css file.

This is an ASP.NET MVC4 application.  I guess I missed that part of the CodeMirror tutorial, but it bothered me enough to blog about.  Fix is as simple as:

<link href="/Scripts/CodeMirror/lib/codemirror.css" rel="stylesheet" type="text/css"></link>

Friday, December 30, 2011

WP7 Mouse LongPress/Hold with Reactive Extensions (Rx)

So, I'm digging through some old code and finding whatever little snippets that I believe others may find useful.  This one in particular allows you to handle a long-press event (pressing on the screen for longer than a specified time period), which I do not believe WP7 controls have by default; it's been a while since I've touched WP7 and haven't kept up with the SDK.

Anyway, the code uses Reactive Extensions to handle this gesture.  Lets pretend that we have a control, a stackpanel perhaps.  We can use the following code to handle the user pressing and holding onto our control for 1.1 seconds:

var stackpanel = new StackPanel();

var mousedownevent = Observable.FromEvent<MouseButtonEventArgs>(stackpanel, "MouseLeftButtonDown");
var mouseupevent = Observable.FromEvent<MouseButtonEventArgs>(stackpanel, "MouseLeftButtonUp");

var mouseholdevent = mousedownevent.Delay(TimeSpan.FromSeconds(1.1)).TakeUntil(mouseupevent).Repeat();

mouseholdevent.Subscribe(x => MessageBox.Show("LongPress with Rx!"));

I just thought this was something cool with reactive extensions so I decided to share it with everyone :)

Segmenting IEnumerable into equal-sized chunks

A while ago, I found myself submitting data to a server, but the data needed to be chunked before being submitted; the reason for this was that server only allowed approximately 50 values to be submitted at a time.  The data was in a class inheriting from IEnumerable, so I figured why not write a simple extension method to segment data.  Easy peasy, but useful if needed.

public static class Extensions
{
    public static IEnumerable<IEnumerable<T>> Segment<T>(this IEnumerable<T> data, int segmentSize)
    {
        double dataSize = data.Count();
        var segmentCount = segmentSize == 0 ? 0 : (int)Math.Ceiling(dataSize / segmentSize);
        return Enumerable.Range(0, segmentCount).Select(i => data.Skip(i * segmentSize).Take(segmentSize));
    }
}

Using the extension method is as easy as:

var segments = Enumerable.Range(1, 10).Segment(3);

The results of running the above code is as follows:


Probably not the best solution since it does iterate over the collection multiple times, but it gets the job done.  Enjoy.