145 lines
4.2 KiB
C#
145 lines
4.2 KiB
C#
//
|
|
// Copyright (c) Antmicro
|
|
//
|
|
// Full license details are defined in the 'LICENSE' file.
|
|
//
|
|
using System;
|
|
using System.IO;
|
|
using System.Collections.Generic;
|
|
using Xwt.Drawing;
|
|
|
|
namespace TermSharp.Vt100
|
|
{
|
|
public class Vt100ITermFileEscapeCodeHandler
|
|
{
|
|
public static bool TryParse(string encodedCommand, out Vt100ITermFileEscapeCodeHandler handler)
|
|
{
|
|
handler = new Vt100ITermFileEscapeCodeHandler();
|
|
|
|
if(!encodedCommand.StartsWith(FileCommandHeader))
|
|
{
|
|
handler.Error = $"Unexpected command type: {encodedCommand}";
|
|
return false;
|
|
}
|
|
|
|
// no, this is not a typo - we are splittin on `:` because the full command looks like:
|
|
// ESC ] 1337 ; File = [arguments] : base-64 encoded file contents ^G
|
|
// for details see: https://iterm2.com/documentation-images.html
|
|
var split = encodedCommand.Split(new [] { ':' }, 2);
|
|
if(split.Length != 2)
|
|
{
|
|
handler.Error = $"Unexpected command format: {encodedCommand}";
|
|
return false;
|
|
}
|
|
|
|
if(!handler.TryParseArguments(split[0].Substring(FileCommandHeader.Length)))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(!handler.TryParseImage(split[1]))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public string Error { get; private set; }
|
|
public Image Image { get; private set; }
|
|
|
|
private const string FileCommandHeader = "File=";
|
|
|
|
private static bool InlineHandler(Vt100ITermFileEscapeCodeHandler handler, string argument)
|
|
{
|
|
if(argument == "0")
|
|
{
|
|
handler.Error = $"Only inline images are supported";
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private static bool Noop(Vt100ITermFileEscapeCodeHandler handler, string argument)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
private bool TryParseArguments(string arguments)
|
|
{
|
|
if(arguments.Length == 0)
|
|
{
|
|
// nothing to parse
|
|
return true;
|
|
}
|
|
|
|
var tags = arguments.Split(new [] { ';' });
|
|
foreach(var tag in tags)
|
|
{
|
|
// name is base64 encoded and can contain the `=` character
|
|
var splittedTag = tag.Split(new [] { '=' }, 2);
|
|
if(splittedTag.Length != 2)
|
|
{
|
|
Error = $"Unexpected tag format: {tag}";
|
|
return false;
|
|
}
|
|
|
|
if(!tagHandlers.TryGetValue(splittedTag[0], out var handler))
|
|
{
|
|
Error = $"Unsupported tag: {(splittedTag[0])}";
|
|
return false;
|
|
}
|
|
|
|
if(!handler(this, splittedTag[1]))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool TryParseImage(string encodedImage)
|
|
{
|
|
byte[] imageBytes = null;
|
|
|
|
try
|
|
{
|
|
imageBytes = Convert.FromBase64String(encodedImage);
|
|
}
|
|
catch(FormatException e)
|
|
{
|
|
Error = $"Base64-encoded image format error: {(e.Message)}";
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
using(var stream = new MemoryStream(imageBytes))
|
|
{
|
|
Image = Image.FromStream(stream);
|
|
}
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
Error = $"Unsupported image format error: {(e.Message)}";
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private readonly Dictionary<string, Func<Vt100ITermFileEscapeCodeHandler, string, bool>> tagHandlers = new Dictionary<string, Func< Vt100ITermFileEscapeCodeHandler, string, bool>>
|
|
{
|
|
{ "name", Noop },
|
|
{ "size", Noop },
|
|
{ "width", Noop },
|
|
{ "height", Noop },
|
|
{ "preserveAspectRatio", Noop },
|
|
{ "inline", InlineHandler }
|
|
};
|
|
}
|
|
}
|
|
|