witters:World

see martin code

About the author

Martin Witters is a software developer at Xpress Technologies in Jacksonville, FL.
E-mail me Send mail

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2009

FTPS over TLS/SSL using C#

One of the projects I'm working on has a requirement to send a document over a secure FTP connection.  The .NET framework has a built-in class to handle FTP (FTPWebRequest) so that was a good starting point.

The documentation for FTPWebRequest does not provide a great deal of detail on securing the communications between the client and the server.  There is simply a boolean property named EnableSSL to turn the encryption on or off.  Sounded pretty simple, so here's what I came up with for my upload method:

public bool UploadFile(Uri serverUri, string userName, string password, string fileName)
{
    // the serverUri should start with the ftp:// scheme.
    if (serverUri.Scheme != Uri.UriSchemeFtp)
        return false;

    try
    {
        // get the object used to communicate with the server.
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverUri);
        request.EnableSsl = true;
        request.Credentials = new NetworkCredential(userName, password);
        request.Method = WebRequestMethods.Ftp.UploadFile;

        // read file into byte array
        StreamReader sourceStream = new StreamReader(fileName);
        byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
        sourceStream.Close();
        request.ContentLength = fileContents.Length;

        // send bytes to server
        Stream requestStream = request.GetRequestStream();
        requestStream.Write(fileContents, 0, fileContents.Length);
        requestStream.Close();

        FtpWebResponse response = (FtpWebResponse)request.GetResponse();
        Console.WriteLine("Response status: {0}", response.StatusDescription);
    }
    catch (Exception exc)
    {
        throw exc;
    }

    return true;
}

 

When I ran my app with that method, things didn't work quite like I wanted them to.  Here's the error I ended up with: "System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure."

The problem is there is no validation procedure.  None of the MSDN articles I read said anything about certificate validation.  So after much googling, I finally found the missing piece of code in a forum post.  So I added a validation procedure and assigned it as the ServicePointManager.ServerCertificateValidationCallback.

public Program()
{
    ServicePointManager.ServerCertificateValidationCallback = AcceptAllCertificatePolicy;
}

public bool AcceptAllCertificatePolicy(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    return true;
}

 

With that, my secure FTP was a success!  Of course, in real-world applications you will want to do some actual validation of the server certificate, but I'll leave that as an exercise for the reader.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by martin on Friday, December 12, 2008 8:10 PM
Permalink | Comments (0) | Post RSSRSS comment feed

XAML Power Toys

Karl Shifflett recently released the latest update to XAML Power Toys.  This is a great VS add-in that makes WPF/Silverlight development much easier and faster.  His blog has a great breakdown of all the features, including a few Silverlight tutorials covering some of the major features.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by martin on Friday, October 24, 2008 3:54 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Essential Visual Studio Tips & Tricks

I came across this great post this morning on Stephen Walther's blog.  He talks about some tips and tricks that you may not know about in Visual Studio.  I've been using a few of these, but there are some here I am glad to know about.

Currently rated 2.3 by 3 people

  • Currently 2.333333/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by martin on Friday, October 24, 2008 10:58 AM
Permalink | Comments (1) | Post RSSRSS comment feed

Selecting the input tray when printing XPS documents

There are many examples on the web of how to print an XPS document, and for the most part they are relatively simple.  But when my application needed to do something crazy (like...I don't know...tell the document which tray to print to), the myriads of how-to's proved pretty much worthless.  In fact, the only useful information I found on the subject was from a post on MSDN forums.  This post proved extremely helpful, even containing a c# code sample that I could use almost as-is.

But when I got to the point of implementing that code, I hit a snag.  It seems that the document would always print to the last tray on the printer, even though I was telling it to print to a specific tray.  It turns out, there was a little bit of detail missing from the sample code, namely a namespace attribute that needs to be added to the xml document that comprises the PrintTicket.  The URI for that namespace is likely to be different for each printer your application prints to, so you need to discover it at runtime.

Here's the updated sample, with my slight modifications:

public static class XpsPrinterUtils
{
private static string GetInputBinName(string printerName, int binIndex, out string nameSpaceURI)
{
string binName = string.Empty;
// get PrintQueue of Printer from the PrintServer
LocalPrintServer printServer = new LocalPrintServer();
PrintQueue printQueue = printServer.GetPrintQueue(printerName);
// get PrintCapabilities of the printer
MemoryStream printerCapXmlStream = printQueue.GetPrintCapabilitiesAsXml();
// read the JobInputBins out of the PrintCapabilities
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(printerCapXmlStream);
// create NamespaceManager and add PrintSchemaFrameWork-Namespace (should be on DocumentElement of the PrintTicket)
// Prefix: psf  NameSpace: xmlDoc.DocumentElement.NamespaceURI = "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable);
manager.AddNamespace(xmlDoc.DocumentElement.Prefix, xmlDoc.DocumentElement.NamespaceURI);
nameSpaceURI = xmlDoc.ChildNodes[1].GetNamespaceOfPrefix("ns0000");
// and select all nodes of the bins
XmlNodeList nodeList = xmlDoc.SelectNodes("//psf:Feature[@name='psk:JobInputBin']/psf:Option", manager);
// fill Dictionary with the bin-names and values
if (nodeList.Count > binIndex)
{
binName = nodeList[binIndex].Attributes["name"].Value;
}    
return binName;
}
public static PrintTicket ModifyPrintTicket(PrintTicket ticket, string featureName, string newValue, string nameSpaceURI)
{
if (ticket == null)
{
throw new ArgumentNullException("ticket");
}
// read Xml of the PrintTicket
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(ticket.GetXmlStream());
// create NamespaceManager and add PrintSchemaFrameWork-Namespace hinzufügen (should be on DocumentElement of the PrintTicket)
// Prefix: psf  NameSpace: xmlDoc.DocumentElement.NamespaceURI = "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
XmlNamespaceManager manager = new XmlNamespaceManager(xmlDoc.NameTable);
manager.AddNamespace(xmlDoc.DocumentElement.Prefix, xmlDoc.DocumentElement.NamespaceURI);
// search node with desired feature we're looking for and set newValue for it
string xpath = string.Format("//psf:Feature[@name='{0}']/psf:Option", featureName);
XmlNode node = xmlDoc.SelectSingleNode(xpath, manager);
if (node != null)
{
if (newValue.StartsWith("ns0000"))
{
// add namespace to xml doc
XmlAttribute namespaceAttribute = xmlDoc.CreateAttribute("xmlns:ns0000");                
namespaceAttribute.Value = nsNameSpaceURI;
xmlDoc.DocumentElement.Attributes.Append(namespaceAttribute);
}
node.Attributes["name"].Value = newValue;
}
// create a new PrintTicket out of the XML
MemoryStream printTicketStream = new MemoryStream();
xmlDoc.Save(printTicketStream);
printTicketStream.Position = 0;
PrintTicket modifiedPrintTicket = new PrintTicket(printTicketStream);
// for testing purpose save the printticket to file
//FileStream stream = new FileStream("modPrintticket.xml", FileMode.CreateNew, FileAccess.ReadWrite);
//modifiedPrintTicket.GetXmlStream().WriteTo(stream);
return modifiedPrintTicket;
}
}
// example of calling above code
string nameSpaceURI = string.Empty;
string selectedBin = XpsPrinterUtils.GetInputBinName(PrinterName, PaperBin, out nameSpaceURI); 
PrintTicket myPrintTicket = XpsPrinterUtils.ModifyPrintTicket(defaultPrintTicket, "psk:JobInputBin", selectedBin, nameSpaceURI); 

Currently rated 4.3 by 3 people

  • Currently 4.333333/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:
Posted by martin on Friday, May 23, 2008 2:48 PM
Permalink | Comments (2) | Post RSSRSS comment feed

VS 2008 and .NET Framework 3.5 SP1 Beta released

Scott Guthrie and Tim Sneath have very informative posts about all the new features and improvements in this release.  I'm particularly excited about the performance improvements in WPF, as well as the improvements to the WPF designer in Visual Studio.

Currently rated 1.0 by 1 people

  • Currently 1/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by martin on Tuesday, May 13, 2008 1:44 PM
Permalink | Comments (0) | Post RSSRSS comment feed