Author Archives: anoriginalidea

About anoriginalidea

A self described software generalist, currently having adventures in mobility, human computer interaction and .net development.

Backing up your files without file locks on Windows

Standard

Make perfect copies every time with Volume Shadow Copy

Do you have some files you want backed up but can’t afford the downtime?

As part of the eidy we have a shared game world for the team to experiment with running windows server.  Windows has a feature called “Volume Shadow Copy” that allows you to copy files while they are in use.

Shadow Copy is used in taking manual or automatic backup copies or snapshots of computer files or volumes, even when they are in use. It is implemented as a Windows service called the Volume Shadow Copy service. A software VSS provider service is also included as part of Windows to be used by Windows applications. Shadow Copy technology requires the file system to be NTFS to be able to create and store shadow copies. Shadow Copies can be created on local and external (removable or network) volumes by any Windows component that uses this technology, such as when creating a scheduled Windows Backup or automatic System Restore point. (From: https://en.wikipedia.org/wiki/Shadow_Copy)

I didn’t particularly want to use backup.  I just wanted to do a simple file copy.

The way this works is that you mount the folder you want to copy as a special drive letter, which you then copy the files from.  Weird eh?

I did this using a cool little program called “ShadowSpawn” that allows you to execute a command using a volume shadow copy mount.

Using Windows Scheduler I execute the following command:

shadowspawn C:\eidy Q: robocopy Q:\ D:\eidybackup /s

(The volume “Q:\” is a temporary driver letter, “D:\” is a cloud synced volume)

It’s easy to setup, and may help with your simplistic copying needs.

Using Amazon AWS DynamoDb from Powershell

Standard

Serious Cat -   Update Dynamodb in Powershell? You cant be serious

Dynamo Db can be very useful in AWS scripting for persisting variable values.

It seems the most common way of doing this is to use the “aws” cli tool.  For Powershell users there isn’t an equivalent commandlet, so I see alot of examples calling the aws commandline tool from within Powershell.

For Powershell people there must be a better way, and that way is to call the AWS SDK directly!

Here’s an example that updates a simple table with a “Name” (key) and “Value” columns.  I’ve encapsulated this in a pair of functions of utility.

Hope you find this useful.

function UpdateVar
{
Param([string]$secretKey,
[string]$secretAccessKey,
[string]$regionName,
[string]$name,
[string]$value)

Add-Type -Path (${env:ProgramFiles(x86)} + “\AWS SDK for .NET\bin\net45\AWSSDK.dll”)

$regionEndpoint=[Amazon.RegionEndPoint]::GetBySystemName($regionName)
$client=[Amazon.AWSClientFactory]::CreateAmazonDynamoDBClient($secretKey,$secretAccessKey,$regionEndpoint)

$req = New-Object Amazon.DynamoDBv2.Model.UpdateItemRequest
$req.TableName = “mytable”

# Key
$req.Key = New-Object ‘system.collections.generic.dictionary[string,Amazon.DynamoDBv2.Model.AttributeValue]’
$keyattribute = New-Object Amazon.DynamoDBv2.Model.AttributeValue
$keyattribute.S = $name
$req.Key.Add(“Name”, $keyattribute)

# Expression Attribute Names
$req.ExpressionAttributeNames = New-Object ‘system.collections.generic.dictionary[string,string]’
$req.ExpressionAttributeNames.Add(“#V”,”Value”)
# Expression Attribute Values

$valueattribute = New-Object Amazon.DynamoDBv2.Model.AttributeValue
$valueattribute.S = $value
$req.ExpressionAttributeValues = New-Object ‘system.collections.generic.dictionary[string,Amazon.DynamoDBv2.Model.AttributeValue]’
$req.ExpressionAttributeValues.Add(“:value”,$valueattribute)
$req.UpdateExpression = “SET #V = :value”

$client.UpdateItem($req)
return $true
}

function GetVar
{
Param([string]$secretKey,
[string]$secretAccessKey,
[string]$regionName,
[string]$name)

Add-Type -Path (${env:ProgramFiles(x86)} + “\AWS SDK for .NET\bin\net45\AWSSDK.dll”)

$regionEndpoint=[Amazon.RegionEndPoint]::GetBySystemName($regionName)
$client=[Amazon.AWSClientFactory]::CreateAmazonDynamoDBClient($secretKey,$secretAccessKey,$regionEndpoint)

$req = New-Object Amazon.DynamoDBv2.Model.GetItemRequest
$req.TableName = “mytable”
$req.Key = New-Object ‘system.collections.generic.dictionary[string,Amazon.DynamoDBv2.Model.AttributeValue]’

$keyattribute = New-Object Amazon.DynamoDBv2.Model.AttributeValue
$keyattribute.S = $name
$req.Key.Add(“Name”, $keyattribute)

$resp = $client.GetItem($req)

$res = $resp.GetItemResult
return $res.Item[“Value”].S

}

$secretKeyID=”xxxxxxxxxxxxxxxxx”
$secretAccessKeyID=”yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy”
$region=”ap-southeast-2″

UpdateVar $secretKeyID $secretAccessKeyID $region “SomeKey” “somevalue”

$val = GetVar $secretKeyID $secretAccessKeyID $region “SomeKey”

Uploading large files using HTML5, Microsoft MVC 3 and FineUploader

Standard

image_thumb.png

File sizes are getting larger (eg media files such as video) and increasingly web applications must be able to progressively go beyond the simple file input field.

Since the HTML5 spec supported the file api it is now possible to slice up very large files and send these progressively.

The FineUploader javascript library allows this to be done in a nice way.  Although the clientside example is complete, currently the MVC serverside example does not support file chunking.  (Although the Java example does)

Here’s an example I’ve created, based on the original that does.

I know that it would be better to update github (and perhaps I will) but for the time being It’s quicker to present it here.  I hope it helps someone and you are welcome to integrate it with FineUploaders example yourself.

Clientside code:

<script>
$(document).ready(function () {
$(‘#fine-uploader’).fineUploader({
request: {
endpoint: ‘Upload/UploadFile’
},
chunking: {
enabled: true,
chunksize: 100
},
debug: true,
autoupload: true
});
});
</script>

MVC Method:

[HttpPost]
public FineUploaderResult UploadFile(FineUpload upload)
{

// asp.net mvc will set extraParam1 and extraParam2 from the params object passed by Fine-Uploader
var dir = Server.MapPath(“~/App_Data/uploads”);

try
{

if (upload.IsMultipart())
{
// Save the part
var filePath = Path.Combine(dir, upload.PartUuid + “.” + upload.PartIndex);
upload.SaveAs(filePath,true);

// If last part do the merge
if(upload.PartIndex == (upload.TotalParts -1))
{
ulong bytesWritten = 0;
using (
var output = System.IO.File.OpenWrite(Path.Combine(dir, upload.OriginalFilename))
)
{
for (var i = 0; i < upload.TotalParts; i++) { // Open part file using ( var input = System.IO.File.OpenRead(Path.Combine(dir, upload.PartUuid + “.” + i)) ) { var buff = new byte[1]; while (input.Read(buff, 0, 1) > 0)
{
output.WriteByte(buff[0]);
bytesWritten++;
}
input.Close();
}
output.Flush();
}
output.Close();

if (bytesWritten != upload.FileSize)
{
throw new ApplicationException(“Upload Error. Please try again”);
}

// Clean up part files
for (var i = 0; i < upload.TotalParts; i++)
{
System.IO.File.Delete(Path.Combine(dir, upload.PartUuid + “.” + i));
}

}

}

}
else
{
var filePath = Path.Combine(dir, upload.Filename);
upload.SaveAs(filePath,true);
}

}
catch (Exception ex)
{
return new FineUploaderResult(false, error: ex.Message);
}

// the anonymous object in the result below will be convert to json and set back to the browser
return new FineUploaderResult(true, new { extraInformation = 12345 });
}
FineUploader.cs:

using System.IO;
using System.Web.Mvc;

namespace FineUploader
{
[ModelBinder(typeof(ModelBinder))]
public class FineUpload
{

private const string FILENAME_PARAM = “qqfile”;
private const string PART_INDEX_PARAM = “qqpartindex”;
private const string FILE_SIZE_PARAM = “qqtotalfilesize”;
private const string TOTAL_PARTS_PARAM = “qqtotalparts”;
private const string UUID_PARAM = “qquuid”;
private const string PART_FILENAME_PARAM = “qqfilename”;
private const string BLOB_NAME_PARAM = “qqblobname”;

public string Filename { get; set; }
public Stream InputStream { get; set; }
public int PartIndex { get; set; }
public int TotalParts { get; set; }
public string OriginalFilename { get; set; }
public string PartUuid { get; set; }
public ulong FileSize { get; set; }
public bool IsMultipart()
{
return (TotalParts > 0);
}
public void SaveAs(string destination, bool overwrite = false, bool autoCreateDirectory = true)
{
if (autoCreateDirectory)
{
var directory = new FileInfo(destination).Directory;
if (directory != null) directory.Create();
}

using (var file = new FileStream(destination, overwrite ? FileMode.Create : FileMode.CreateNew))
InputStream.CopyTo(file);
}

public class ModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var request = controllerContext.RequestContext.HttpContext.Request;
var formUpload = request.Files.Count > 0;

// find filename
var xFileName = request.Headers[“X-File-Name”];
var qqFile = request[FILENAME_PARAM];
var qqpartindex = request[PART_INDEX_PARAM];

var formFilename = formUpload ? request.Files[0].FileName : null;

var upload = new FineUpload
{
Filename = xFileName ?? qqFile ?? formFilename,
InputStream = formUpload ? request.Files[0].InputStream : request.InputStream,

};
int someval;
if (int.TryParse(qqpartindex, out someval))
{
upload.PartIndex = someval;
upload.OriginalFilename = request[PART_FILENAME_PARAM];
upload.TotalParts = int.Parse(request[TOTAL_PARTS_PARAM]);
upload.PartUuid = request[UUID_PARAM];
upload.FileSize = ulong.Parse(request[FILE_SIZE_PARAM]);
}

return upload;
}
}

}
}

This code is supplied as is, for informational purposes only with no warranties or statements about being fit for purpose and stuff.

Its time. I’m making a stand. MyNamingConventionManifesto.

Standard

Variable names, filenames and other technical names.  Hungarian notion, abbreviations, verbosity, camel case and mixed case.  How many of my projects have used mixtures of these conventions?  How often do I forget what abbrev I usd????

?!It_never_ends!?   

no-longer   

I-AM-SICK-OF-IT!

_this_has_to_stop

<rant>It is time to do away with inconsistency forever.  </rant>

I am happy to comply with the conventions of a language (eg in .net mixed case is used for public attributes and properties whereas camel case is used for parameters) or the conventions of an existing project, but if there isn’t any, MyNamingConventionManifesto comes into play.

The decisions are around:

CASE (Upper, Lower, Mixed or Camel Case) 

DELIMITER (None, Minus, Underscore or Space)

PREFIX

SUFFIX

So, I hereby declare that my naming convention will not use prefixes or suffixes, neither will it use delimiters.  In short, this is:

MyNamingConventionManifesto 

 

ThankyouThatWillBeAll

 

Simple object dumping extension method for CSharp

Standard

Here’s a useful little extension method I created to dump fields and properties to the console of an object in CSharp.  

It demonstrates simple reflection and extension method syntax.

 

 

public static class ObjectExtensions
{
public static void DumpProperties(this object obj)
{
Console.WriteLine(obj.GetType().Name);
Console.WriteLine("{");
foreach (var fld in obj.GetType().GetFields())
{
Console.WriteLine(String.Format("{0} = \"{1}\"", fld.Name, fld.GetValue(obj)));
}
foreach (var prop in obj.GetType().GetProperties())
{
if(prop.CanRead) Console.WriteLine(String.Format("{0} = \"{1}\"", prop.Name,prop.GetValue(obj, null)));
}
Console.WriteLine("}");
}
}

 

 

 

Creating a an instance in EC2 with .net and passing parameters

Standard

When starting an Amazon EC2 instance, you can pass something called “user metadata”.  This can be a file or values.  These values are not stored in an environmental variable or file on the new instance, but can instead be retrieved by doing a HTTP Get to a “special” IP address to retrieve those values.

For example:

1.  Create the instance

RunInstancesResponse response = Client.RunInstances(new RunInstancesRequest()
  .WithImageId(ami_id)
  .WithInstanceType(instance_type)
  .WithKeyName(YOUR_KEYPAIR_NAME)
  .WithMinCount(1)
  .WithMaxCount(max_number_of_instances)
  .WithUserData(Convert.ToBase64String(Encoding.UTF8.GetBytes(bootScript.Replace("\r", ""))))
);

2.  In a startup script on the instance, make a call like this:

GET http://169.254.169.254/latest/user-data
1234,fred,reboot,true | 4512,jimbo, | 173,,,

See the links below for further info

 

 

 

 

 

Links

http://stackoverflow.com/questions/7420368/how-to-start-an-amazon-ec2-instance-programmatically-in-net

http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html

What every phonegap developer on windows phone 7 needs

Standard

 

Error logging!  An unfortunate side effect of developing apps in Javascript in mobile IE9 is that there doesn’t appear to be any error dialogs.

Try the following Javascript:

 

// provide our own console if it does not exist, huge dev aid!
if (typeof window.console == “undefined”) {
window.console = { log: function (str) { window.external.Notify(str); } };
}

// output any errors to console log, created above.
window.onerror = function (msg,url,linenumber) {
console.log(“Error ::” + msg + ” in ” + url + ” at line ” + linenumber);
};

console.log(“Installed console ! “);

This also gives you a “console.log” for free.

 

Enjoy!

 

 

Aspect Oriented Programming in Javascript

Standard

 

In designing javascript for modularity and “separation of concerns”, I was pleasantly surprised to discover a way of implementing AOP (Aspect Oriented Programming) in Javascript.

 

AOP can be useful for automatically “wrapping” methods to provide tracing, error logging or caching.

In this example, we are “wrapping” a method to show an alert when a method starts and finishes:

$.aop.around({ target: homelinksModel, method: 'get' }
 , function (invocation) {
alert("Method Call");
 
var ret = return invocation.proceed(); // This line calls the original method
alert("After Call");
return ret;
});

I used it for caching using Lawnchair  (an abstraction around local storage on client browsers).  It is designed to cache the result of data calls to the server.

$.aop.around({ target: homelinksModel, method: 'get' }
 , function (invocation) {
var lc = new Lawnchair(function () { });
var keyName = 'homelinksModel' + invocation.method;
var rec;
lc.get(keyName, function (ret) {
if (ret == null) {
    res = invocation.proceed()
    lc.save({ key: keyName, value: res });
    rec = res;
 }
 else {
 rec = ret.value;
 }
});
return rec;
}); // </aop>

I’m still learning Lawnchair, so there’s probably better ways of implementing this, but I thought a “useful” example might be helpful.

Peter Chung has an excellent article about Jquery AOP if you’d like to learn more.

There’s not alot of recent “action” around AOP in the Javascript space (Google Search).   I suspect that either some of it’s functionality is automatically part of jQuery or that the Javascript world isn’t mature enough yet to care much.    Perhaps it’s the former.

Over the past few days I’ve had a marvelous time implementing the MVVM pattern in Javascript.  I’m discovering all my favourite technologies are there, such as object databases (Lawnchair), binding (Knockout) and much more.  I hope to be blogging more about some of these soon.

Links

 

 

Returning data from an MVC method with a small cute ActionResult

Standard

image

In order return data from an MVC method, Microsoft provide a useful ActionResult object called JSONResult.  JSONResult exposes a convenient Data property that you can use to serialize an object to JSON.

Here’s how it can be used:

var res = new JsonResult();
res.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
res.Data = someObject;
return res;

Pretty easy to use.   Unfortunately there’s no matching XMLResult class if you want to return a scrap of XML instead.  In the MVCContrib project on codeplex there’s an XMLResult, but it’s event signature is slightly different.

I’ve modified this class to provide the same signature. 

Here’s the usage:

var res = new XmlResult();
res.Data = someObject;
return res;

Here’s the class:

using System.Web.Mvc;
using System.Xml.Serialization;

namespace Sample
{
    /// <summary>
    /// Action result that serializes the specified object into XML and outputs it to the response stream.
    /// </summary>
    public class XmlResult : ActionResult
    {
        private object _objectToSerialize;
        private XmlAttributeOverrides _xmlAttribueOverrides;

        /// <summary>
        /// Creates a new instance of the XmlResult class.
        /// </summary>
        /// <param name="objectToSerialize">The object to serialize to XML.</param>
        public XmlResult()
        {
      
        }

        /// <summary>
        /// Creates a new instance of the XmlResult class.
        /// </summary>
        /// <param name="objectToSerialize">The object to serialize to XML.</param>
        public XmlResult(object objectToSerialize)
        {
            _objectToSerialize = objectToSerialize;
        }

        /// <summary>
        /// Creates a new instance of the XMLResult class.
        /// </summary>
        /// <param name="objectToSerialize">The object to serialize to XML.</param>
        /// <param name="xmlAttributeOverrides"></param>
        public XmlResult(object objectToSerialize, XmlAttributeOverrides xmlAttributeOverrides)
        {
            _objectToSerialize = objectToSerialize;
            _xmlAttribueOverrides = xmlAttributeOverrides;
        }

        /// <summary>
        /// The object to be serialized to XML.
        /// </summary>
        public object Data
        {
            get
            { return _objectToSerialize; }
            set
            {
                _objectToSerialize = value;
            }
        }

        /// <summary>
        /// Serialises the object that was passed into the constructor to XML and writes the corresponding XML to the result stream.
        /// </summary>
        /// <param name="context">The controller context for the current request.</param>
        public override void ExecuteResult(ControllerContext context)
        {
            if (_objectToSerialize != null)
            {
                var xs = (_xmlAttribueOverrides == null) ?
                    new XmlSerializer(_objectToSerialize.GetType()) :
                    new XmlSerializer(_objectToSerialize.GetType(), _xmlAttribueOverrides);
                context.HttpContext.Response.ContentType = "text/xml";
                xs.Serialize(context.HttpContext.Response.Output, _objectToSerialize);
            }
        }
    }
}

Data Uris–A way of embedding images in your html page or UIWebView

Standard

image

Currently I’m investigating ways of using  UIWebView to render a user interface.  

I’d like to re-purpose some server side html form rendering logic so that it can be resused on the iPhone, Android and Windows Phone. 

Modern forms incorporate more than simple form elements however.  They may include data, such as images.

By default, the UIWebview supports images in the “bundle” and images in the documents area. 

What if I want to create images in memory, then display these in the HTML?

An little known feature of many modern web browsers (including Webkit) is datauris.  A datauri allows data to be embedded in a webpage where a url would usually be.

Here’s an example:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />
There are disadvantages however, which are the obvious effect this will have on caching and pagesize.
The Stackflow article Display Local UI Image On a UIWebView shows how to this, replicated here for your convenience.
This code demonstrates reading a file from the local bundle, then embedding into the background image, in the html dom of a UIWebView:

#import "NSString+DataURI.h"

#import "NSData+Base64.h"

...

-(void)webViewDidFinishLoad:(UIWebView *)webView

{

    NSString *imgPath = [[NSBundle mainBundle] pathForResource:@"image" ofType:@"png"];

    NSData *imgData = [NSData dataWithContentsOfFile:imgPath];

    NSString *imgB64 = [[imgData base64Encoding] pngDataURIWithContent];

    NSString *javascript = [NSString stringWithFormat:@"document.body.style.backgroundImage='url(%@)';", imgB64];

    [webView stringByEvaluatingJavaScriptFromString:javascript];

}

This code uses the following utility functions that provide the base 64 encoding support:

NSData+Base64.h

@interface NSData (Base64)

+ (NSData *)dataWithBase64EncodedString:(NSString *)string;

- (id)initWithBase64EncodedString:(NSString *)string;

- (NSString *)base64Encoding;

- (NSString *)base64EncodingWithLineLength:(unsigned int) lineLength;

@end

NSData.Base64.m

#import "NSData+Base64.h"

static char encodingTable[64] = {

'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',

'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',

'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',

'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' };

@implementation NSData (VQBase64)

- (id)initWithString:(NSString *)string {

    if ((self = [super init])) {

        [self initWithBase64EncodedString:string];

    }

    return self;

}

+ (NSData *) dataWithBase64EncodedString:(NSString *) string {

    return [[[NSData allocWithZone:nil] initWithBase64EncodedString:string] autorelease];

}

- (id) initWithBase64EncodedString:(NSString *) string {

    NSMutableData *mutableData = nil;

    if( string ) {

        unsigned long ixtext = 0;

        unsigned long lentext = 0;

        unsigned char ch = 0;

        unsigned char inbuf[4], outbuf[3];

        short i = 0, ixinbuf = 0;

        BOOL flignore = NO;

        BOOL flendtext = NO;

        NSData *base64Data = nil;

        const unsigned char *base64Bytes = nil;

        // Convert the string to ASCII data.

        base64Data = [string dataUsingEncoding:NSASCIIStringEncoding];

        base64Bytes = [base64Data bytes];

        mutableData = [NSMutableData dataWithCapacity:[base64Data length]];

        lentext = [base64Data length];

        while( YES ) {

            if( ixtext >= lentext ) break;

            ch = base64Bytes[ixtext++];

            flignore = NO;

            if( ( ch >= 'A' ) && ( ch <= 'Z' ) ) ch = ch - 'A';

            else if( ( ch >= 'a' ) && ( ch <= 'z' ) ) ch = ch - 'a' + 26;

            else if( ( ch >= '0' ) && ( ch <= '9' ) ) ch = ch - '0' + 52;

            else if( ch == '+' ) ch = 62;

            else if( ch == '=' ) flendtext = YES;

            else if( ch == '/' ) ch = 63;

            else flignore = YES;

            if( ! flignore ) {

                short ctcharsinbuf = 3;

                BOOL flbreak = NO;

                if( flendtext ) {

                    if( ! ixinbuf ) break;

                    if( ( ixinbuf == 1 ) || ( ixinbuf == 2 ) ) ctcharsinbuf = 1;

                    else ctcharsinbuf = 2;

                    ixinbuf = 3;

                    flbreak = YES;

                }

                inbuf [ixinbuf++] = ch;

                if( ixinbuf == 4 ) {

                    ixinbuf = 0;

                    outbuf [0] = ( inbuf[0] << 2 ) | ( ( inbuf[1] & 0x30) >> 4 );

                    outbuf [1] = ( ( inbuf[1] & 0x0F ) << 4 ) | ( ( inbuf[2] & 0x3C ) >> 2 );

                    outbuf [2] = ( ( inbuf[2] & 0x03 ) << 6 ) | ( inbuf[3] & 0x3F );

                    for( i = 0; i < ctcharsinbuf; i++ )

                        [mutableData appendBytes:&outbuf[i] length:1];

                }

                if( flbreak )  break;

            }

        }

    }

    self = [self initWithData:mutableData];

    return self;

}

#pragma mark -

- (NSString *) base64Encoding {

    return [self base64EncodingWithLineLength:0];

}

- (NSString *) base64EncodingWithLineLength:(unsigned int) lineLength {

    const unsigned char     *bytes = [self bytes];

    NSMutableString *result = [NSMutableString stringWithCapacity:[self length]];

    unsigned long ixtext = 0;

    unsigned long lentext = [self length];

    long ctremaining = 0;

    unsigned char inbuf[3], outbuf[4];

    unsigned short i = 0;

    unsigned short charsonline = 0, ctcopy = 0;

    unsigned long ix = 0;

    while( YES ) {

        ctremaining = lentext - ixtext;

        if( ctremaining <= 0 ) break;

        for( i = 0; i < 3; i++ ) {

            ix = ixtext + i;

            if( ix < lentext ) inbuf[i] = bytes[ix];

            else inbuf [i] = 0;

        }

        outbuf [0] = (inbuf [0] & 0xFC) >> 2;

        outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);

        outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);

        outbuf [3] = inbuf [2] & 0x3F;

        ctcopy = 4;

        switch( ctremaining ) {

            case 1:

                ctcopy = 2;

                break;

            case 2:

                ctcopy = 3;

                break;

        }

        for( i = 0; i < ctcopy; i++ )

            [result appendFormat:@"%c", encodingTable[outbuf[i]]];

        for( i = ctcopy; i < 4; i++ )

            [result appendString:@"="];

        ixtext += 3;

        charsonline += 4;

        if( lineLength > 0 ) {

            if( charsonline >= lineLength ) {

                charsonline = 0;

                [result appendString:@"\n"];

            }

        }

    }

    return [NSString stringWithString:result];

}

@end

  

NSString+DataURI.h

#import <Foundation/Foundation.h>

@interface NSString(DataURI)

- (NSString *) pngDataURIWithContent;

- (NSString *) jpgDataURIWithContent;

@end

NSString+DataURI.m

#import "NSString+DataURI.h"

@implementation NSString(DataURI)

- (NSString *) pngDataURIWithContent;

{

    NSString * result = [NSString stringWithFormat: @"data:image/png;base64,%@", self];

    return result;

}

- (NSString *) jpgDataURIWithContent;

{

    NSString * result = [NSString stringWithFormat: @"data:image/jpg;base64,%@", self];

    return result;

}

@end