using System;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using System.Security.Cryptography;
using System.Text;
using System.Net;
using System.IO;
using System.Threading;
using System.Diagnostics;


public class MsDownload{



   public static void Main(string[] args){   
   
    

    try{    
     
      XslTransform transform = new XslTransform();
      transform.Load(new XmlTextReader( new StringReader(stylesheet)));


      while(true){

      string soapRequest = BuildSoapRequest();
      HttpWebResponse response = SendRequest(soapRequest);    
      string soapResponse = GetResponseString(response); 

      XPathDocument doc   = new XPathDocument(new XmlTextReader(new StringReader(soapResponse)));       
      transform.Transform(doc, null, new XmlTextWriter(new StreamWriter("MsftTop10Downloads.rss")));
      Console.WriteLine("DONE");

      Thread.Sleep(30 * 60 * 1000); /* sleep for 30 minutes */

      }

     
    }catch(WebException e){
     
      if(e.Response != null)
    Console.WriteLine(GetResponseString((HttpWebResponse) e.Response));
      else
    Console.WriteLine(e);     
    }catch(Exception ex){
      Console.WriteLine(ex);
    }

  }
 

    public static HttpWebResponse SendRequest(string soapmessage){

    HttpWebRequest request = (HttpWebRequest) WebRequest.Create(endpoint);

    request.Timeout          = 1 * 60 * 1000;
    request.Method = "POST";
    request.ContentType = "text/xml";
    request.Headers.Add("SOAPAction", "http://www.microsoft.com/GetTopDownloads");
    request.ContentLength = soapmessage.Length;

    StreamWriter myWriter = null;
    try{
      myWriter = new StreamWriter(request.GetRequestStream());
      myWriter.Write(soapmessage);
    } catch(Exception e){
         
      throw new WebException(e.Message, e);
    }finally{
      if(myWriter != null){
        myWriter.Close();    
      }
    }
            
    return (HttpWebResponse) request.GetResponse();

      }

      public static string GetResponseString(HttpWebResponse response){

    StringBuilder sb = new StringBuilder();
    StringWriter writeStream = null;
    StreamReader readStream = null;
       
    writeStream = new StringWriter(sb);
         
    //Retrieve input stream from response and specify encoding
    Stream receiveStream     = response.GetResponseStream();
    Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
       
    // Pipe the stream to a higher level stream reader with the required encoding format.
    readStream = new StreamReader( receiveStream, encode );         
    Char[] read = new Char[256];                                  
    int count = readStream.Read( read, 0, 256 );
       
         
    while (count > 0) {
         
      // Dumps the 256 characters on a string and displays the string to the console.
      writeStream.Write(read, 0, count);
      count = readStream.Read(read, 0, 256);
         
    }  

    return sb.ToString();

      }


  public static string BuildSoapRequest(){

     /* build Nonce */
      string data   = "Carnage4Life";    
      SHA1 sha      = new SHA1CryptoServiceProvider();
      byte[] temp   = sha.ComputeHash(Encoding.Default.GetBytes(data));      
     
      string nonce = Convert.ToBase64String(temp);
   
      /* Build Expired and Created */
      DateTime created = DateTime.Now;
      DateTime expired = created + new TimeSpan(0, 0, 180);


      /* build Digest */
      sha     = new SHA1CryptoServiceProvider();     

      temp = sha.ComputeHash(Encoding.Default.GetBytes( Encoding.Default.GetString(temp) +  created.ToUniversalTime().ToString("s")+ "Z" + pin));
     
      string digest = Convert.ToBase64String(temp);
     
      StringBuilder sb = new StringBuilder();
      StringWriter  sw = new StringWriter(sb);
     
      sw.Write(request, tokenID, digest + "\n", nonce + "\n", created.ToUniversalTime().ToString("s") + "Z", expired.ToUniversalTime().ToString("s") + "Z");
      sw.Close();

      return sb.ToString();
  }


 
  public const string tokenID = "0RBzMjyHym5wBwxvnBXmTYbL6XgaQfAR";
  public const string pin     = "GUnit!";

  public const string endpoint       = "http://ws.microsoft.com/mscomservice/mscom.asmx";

  public static string request = @"<soap:Envelope
  xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'
  xmlns:wsu='http://schemas.xmlsoap.org/ws/2002/07/utility'
  xmlns:wsse='http://schemas.xmlsoap.org/ws/2002/07/secext'> 

  <soap:Header>
    <wsse:Security>
      <wsse:UsernameToken>
        <wsse:Username>{0}</wsse:Username>
        <wsse:Password Type='wsse:PasswordDigest'>{1}</wsse:Password>
        <wsse:Nonce>{2}</wsse:Nonce>
        <wsu:Created>{3}</wsu:Created>
        <wsu:Expires>{4}</wsu:Expires>
      </wsse:UsernameToken>
    </wsse:Security>
  </soap:Header>

  <soap:Body>
    <GetTopDownloads xmlns='http://www.microsoft.com'>
      <topType>Popular</topType> 
      <topN>10</topN> 
      <cultureID>en-US</cultureID>
    </GetTopDownloads>
  </soap:Body>
</soap:Envelope>";

public static string stylesheet = @"<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'
    xmlns:b0rg='http://www.microsoft.com' exclude-result-prefixes='b0rg'>

  <xsl:output method='xml' indent='yes' />

  <xsl:template match='/'>

    <rss><channel>
     <title>Microsoft Top 10 Downloads (en-US)</title>
    <link>http://msdn.microsoft.com/webservices/building/livewebservices/mscom services/default.aspx</link>
    <description>The Microsoft Top 10 Downloads XML Web Service exposed as an RSS feed</description>
    <language>en</language>

     <xsl:for-each select='//b0rg:DownloadSummary'>
      <item>
       <link><xsl:value-of select='b0rg:DetailsUrl' /></link>
       <title><xsl:value-of select='b0rg:ShortName' /></title>
       <description><xsl:value-of select='b0rg:ShortDescription' /></description>
      </item>
     </xsl:for-each>

    </channel></rss>

  </xsl:template>

</xsl:stylesheet>";

}