2015-02-25 04:10:47 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Drawing;
|
2016-11-17 03:04:34 +00:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Text.RegularExpressions;
|
2016-06-20 04:22:43 +00:00
|
|
|
|
using System.Web;
|
2015-02-25 04:10:47 +00:00
|
|
|
|
using System.Windows.Forms;
|
2017-01-08 07:54:09 +00:00
|
|
|
|
using PKHeX.Core;
|
2017-01-12 01:55:42 +00:00
|
|
|
|
using QRCoder;
|
2015-02-25 04:10:47 +00:00
|
|
|
|
|
2018-04-07 04:23:09 +00:00
|
|
|
|
using static PKHeX.Core.MessageStrings;
|
|
|
|
|
|
2017-01-08 07:54:09 +00:00
|
|
|
|
namespace PKHeX.WinForms
|
2015-02-25 04:10:47 +00:00
|
|
|
|
{
|
|
|
|
|
public partial class QR : Form
|
|
|
|
|
{
|
2016-11-29 07:02:25 +00:00
|
|
|
|
private readonly PKM pkm;
|
|
|
|
|
private readonly Image icon;
|
|
|
|
|
private Image qr;
|
2016-11-17 03:47:41 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private readonly string[] Lines;
|
2016-11-29 07:02:25 +00:00
|
|
|
|
private string extraText;
|
2016-11-17 03:47:41 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
public QR(Image qr, Image icon, PKM pk, params string[] lines)
|
2015-02-26 07:12:38 +00:00
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
2016-11-17 03:47:41 +00:00
|
|
|
|
pkm = pk;
|
|
|
|
|
|
|
|
|
|
// Layer on Text
|
|
|
|
|
const int stretch = 50;
|
|
|
|
|
Height += stretch;
|
|
|
|
|
|
2018-05-12 15:41:23 +00:00
|
|
|
|
if (pkm?.Format == 7)
|
2016-11-17 03:47:41 +00:00
|
|
|
|
Height += 40;
|
|
|
|
|
|
|
|
|
|
this.qr = qr;
|
|
|
|
|
this.icon = icon;
|
2017-06-18 01:37:19 +00:00
|
|
|
|
Lines = lines;
|
2016-11-17 03:47:41 +00:00
|
|
|
|
|
2018-05-12 15:41:23 +00:00
|
|
|
|
if (pkm?.Format == 7)
|
2017-06-18 01:37:19 +00:00
|
|
|
|
UpdateBoxSlotCopies(null, null);
|
2016-11-17 03:47:41 +00:00
|
|
|
|
else
|
|
|
|
|
RefreshImage();
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-29 07:02:25 +00:00
|
|
|
|
private void RefreshImage()
|
2016-11-17 03:47:41 +00:00
|
|
|
|
{
|
2017-06-18 01:37:19 +00:00
|
|
|
|
Font font = !Main.Unicode ? FontLabel.Font : FontUtil.GetPKXFont((float)8.25);
|
2015-02-26 07:12:38 +00:00
|
|
|
|
Image preview = new Bitmap(45, 45);
|
|
|
|
|
using (Graphics gfx = Graphics.FromImage(preview))
|
|
|
|
|
{
|
|
|
|
|
gfx.FillRectangle(new SolidBrush(Color.White), 0, 0, preview.Width, preview.Height);
|
2016-11-17 03:47:41 +00:00
|
|
|
|
gfx.DrawImage(icon, preview.Width / 2 - icon.Width / 2, preview.Height / 2 - icon.Height / 2);
|
2015-02-26 07:12:38 +00:00
|
|
|
|
}
|
2015-03-14 02:59:51 +00:00
|
|
|
|
// Layer on Preview Image
|
2018-07-15 01:43:46 +00:00
|
|
|
|
Image pic = ImageUtil.LayerImage(qr, preview, qr.Width / 2 - preview.Width / 2, qr.Height / 2 - preview.Height / 2);
|
2016-11-17 03:47:41 +00:00
|
|
|
|
|
2015-03-14 02:59:51 +00:00
|
|
|
|
Image newpic = new Bitmap(PB_QR.Width, PB_QR.Height);
|
2016-03-12 02:40:08 +00:00
|
|
|
|
using (Graphics g = Graphics.FromImage(newpic))
|
|
|
|
|
{
|
|
|
|
|
g.FillRectangle(new SolidBrush(Color.White), 0, 0, newpic.Width, newpic.Height);
|
|
|
|
|
g.DrawImage(pic, 0, 0);
|
2015-02-26 04:19:43 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
g.DrawString(GetLine(0), font, Brushes.Black, new PointF(18, qr.Height - 5));
|
|
|
|
|
g.DrawString(GetLine(1), font, Brushes.Black, new PointF(18, qr.Height + 8));
|
|
|
|
|
g.DrawString(GetLine(2).Replace(Environment.NewLine, "/").Replace("//", " ").Replace(":/", ": "), font, Brushes.Black, new PointF(18, qr.Height + 20));
|
|
|
|
|
g.DrawString(GetLine(3) + extraText, font, Brushes.Black, new PointF(18, qr.Height + 32));
|
2016-03-12 02:40:08 +00:00
|
|
|
|
}
|
2015-03-14 02:59:51 +00:00
|
|
|
|
PB_QR.BackgroundImage = newpic;
|
2015-02-25 04:10:47 +00:00
|
|
|
|
}
|
2016-11-17 03:47:41 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private string GetLine(int line) => Lines.Length <= line ? string.Empty : Lines[line];
|
|
|
|
|
|
2015-02-25 04:42:05 +00:00
|
|
|
|
private void PB_QR_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2018-04-07 04:23:09 +00:00
|
|
|
|
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgQRClipboardImage)) return;
|
2015-02-25 04:42:05 +00:00
|
|
|
|
try { Clipboard.SetImage(PB_QR.BackgroundImage); }
|
2018-04-07 04:23:09 +00:00
|
|
|
|
catch { WinFormsUtil.Alert(MsgQRClipboardFail); }
|
2015-02-25 04:42:05 +00:00
|
|
|
|
}
|
2018-05-12 15:13:39 +00:00
|
|
|
|
|
2016-06-20 04:22:43 +00:00
|
|
|
|
// QR Utility
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private const string QR6PathBad = "null/#"; // prefix to prevent URL from loading
|
2018-05-12 15:41:23 +00:00
|
|
|
|
private const string QR6Path = "http://lunarcookies.github.io/b1s1.html#";
|
2017-08-13 07:21:42 +00:00
|
|
|
|
private const string DecodeAPI = "http://api.qrserver.com/v1/read-qr-code/?fileurl=";
|
|
|
|
|
private const int QRSize = 365;
|
|
|
|
|
private static readonly string EncodeAPI = $"http://chart.apis.google.com/chart?chs={QRSize}x{QRSize}&cht=qr&chl=";
|
2017-03-11 04:35:18 +00:00
|
|
|
|
|
2017-07-03 04:27:22 +00:00
|
|
|
|
internal static byte[] GetQRData(string address)
|
2016-06-20 04:22:43 +00:00
|
|
|
|
{
|
|
|
|
|
// Fetch data from QR code...
|
2018-04-07 04:23:09 +00:00
|
|
|
|
try { if (address.Length < 4 || !address.StartsWith("http")) { WinFormsUtil.Alert(MsgQRUrlFailPath, address); return null; } }
|
|
|
|
|
catch { WinFormsUtil.Alert(MsgQRUrlFailPath, address); return null; }
|
2017-08-13 07:21:42 +00:00
|
|
|
|
string webURL = DecodeAPI + HttpUtility.UrlEncode(address);
|
|
|
|
|
string data;
|
2016-06-20 04:22:43 +00:00
|
|
|
|
try
|
|
|
|
|
{
|
2017-08-13 07:21:42 +00:00
|
|
|
|
data = NetUtil.GetStringFromURL(webURL);
|
2018-04-07 04:23:09 +00:00
|
|
|
|
if (data.Contains("could not find")) { WinFormsUtil.Alert(MsgQRUrlFailImage); return null; }
|
|
|
|
|
if (data.Contains("filetype not supported")) { WinFormsUtil.Alert(MsgQRUrlFailType, address); return null; }
|
2016-06-20 04:22:43 +00:00
|
|
|
|
}
|
2018-04-07 04:23:09 +00:00
|
|
|
|
catch { WinFormsUtil.Alert(MsgQRUrlFailConnection); return null; }
|
2017-08-13 07:21:42 +00:00
|
|
|
|
|
|
|
|
|
// Quickly convert the json response to a data string
|
|
|
|
|
try { return DecodeQRJson(data); }
|
2018-04-07 04:23:09 +00:00
|
|
|
|
catch (Exception e) { WinFormsUtil.Alert(MsgQRUrlFailConvert, e.Message); return null; }
|
2017-08-13 07:21:42 +00:00
|
|
|
|
}
|
|
|
|
|
private static byte[] DecodeQRJson(string data)
|
|
|
|
|
{
|
|
|
|
|
const string cap = "\",\"error\":null}]}]";
|
|
|
|
|
const string intro = "[{\"type\":\"qrcode\",\"symbol\":[{\"seq\":0,\"data\":\"";
|
|
|
|
|
const string qrcode = "nQR-Code:";
|
|
|
|
|
if (!data.StartsWith(intro))
|
|
|
|
|
throw new FormatException();
|
|
|
|
|
|
|
|
|
|
string pkstr = data.Substring(intro.Length);
|
|
|
|
|
if (pkstr.Contains(qrcode)) // Remove multiple QR codes in same image
|
|
|
|
|
pkstr = pkstr.Substring(0, pkstr.IndexOf(qrcode, StringComparison.Ordinal));
|
|
|
|
|
pkstr = pkstr.Substring(0, pkstr.IndexOf(cap, StringComparison.Ordinal)); // Trim outro
|
|
|
|
|
|
|
|
|
|
if (!pkstr.StartsWith("http") && !pkstr.StartsWith(QR6PathBad)) // G7
|
|
|
|
|
{
|
|
|
|
|
string fstr = Regex.Unescape(pkstr);
|
|
|
|
|
byte[] raw = Encoding.Unicode.GetBytes(fstr);
|
|
|
|
|
// Remove 00 interstitials and retrieve from offset 0x30, take PK7 Stored Size (always)
|
2018-05-12 15:41:23 +00:00
|
|
|
|
return raw.ToList().Where((_, i) => i % 2 == 0).Skip(0x30).Take(0xE8).ToArray();
|
2017-08-13 07:21:42 +00:00
|
|
|
|
}
|
|
|
|
|
// All except G7
|
|
|
|
|
pkstr = pkstr.Substring(pkstr.IndexOf("#", StringComparison.Ordinal) + 1); // Trim URL
|
|
|
|
|
pkstr = pkstr.Replace("\\", ""); // Rectify response
|
|
|
|
|
|
|
|
|
|
return Convert.FromBase64String(pkstr);
|
2016-06-20 04:22:43 +00:00
|
|
|
|
}
|
2017-08-13 07:21:42 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
internal static Image GetQRImage(byte[] data, string server)
|
2016-06-20 04:22:43 +00:00
|
|
|
|
{
|
|
|
|
|
string qrdata = Convert.ToBase64String(data);
|
|
|
|
|
string message = server + qrdata;
|
2017-08-13 07:21:42 +00:00
|
|
|
|
string webURL = EncodeAPI + HttpUtility.UrlEncode(message);
|
2016-06-20 04:22:43 +00:00
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
{
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return NetUtil.GetImageFromURL(webURL);
|
2016-06-20 04:22:43 +00:00
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
2018-04-07 04:23:09 +00:00
|
|
|
|
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgQRUrlFailConnection, MsgQRClipboardUrl))
|
2016-06-20 04:22:43 +00:00
|
|
|
|
return null;
|
|
|
|
|
try { Clipboard.SetText(webURL); }
|
2018-04-07 04:23:09 +00:00
|
|
|
|
catch { WinFormsUtil.Alert(MsgClipboardFailWrite); }
|
2016-06-20 04:22:43 +00:00
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2016-11-17 03:47:41 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private void UpdateBoxSlotCopies(object sender, EventArgs e)
|
2016-11-17 03:47:41 +00:00
|
|
|
|
{
|
|
|
|
|
if (pkm == null || pkm.Format != 7)
|
|
|
|
|
throw new ArgumentException("Can't update QR7 if pkm isn't a PK7!");
|
|
|
|
|
var box = (int) NUD_Box.Value - 1;
|
|
|
|
|
var slot = (int) NUD_Slot.Value - 1;
|
|
|
|
|
var copies = (int) NUD_Copies.Value;
|
2017-01-12 01:55:42 +00:00
|
|
|
|
var new_qr = GenerateQRCode7((PK7)pkm, box, slot, copies);
|
2016-11-17 03:47:41 +00:00
|
|
|
|
qr = new_qr;
|
2016-11-29 07:02:25 +00:00
|
|
|
|
SuspendLayout();
|
|
|
|
|
extraText = $" (Box {box+1}, Slot {slot+1}, {copies} cop{(copies > 1 ? "ies" : "y")})";
|
2016-11-17 03:47:41 +00:00
|
|
|
|
RefreshImage();
|
2016-11-29 07:02:25 +00:00
|
|
|
|
ResumeLayout();
|
2016-11-17 03:47:41 +00:00
|
|
|
|
}
|
2017-01-12 01:55:42 +00:00
|
|
|
|
|
|
|
|
|
// QR7 Utility
|
|
|
|
|
public static Image GenerateQRCode7(PK7 pk7, int box = 0, int slot = 0, int num_copies = 1)
|
|
|
|
|
{
|
|
|
|
|
byte[] data = QR7.GenerateQRData(pk7, box, slot, num_copies);
|
2017-08-13 07:21:42 +00:00
|
|
|
|
return GenerateQRCode(data, ppm: 4);
|
2017-01-12 01:55:42 +00:00
|
|
|
|
}
|
2017-08-13 07:21:42 +00:00
|
|
|
|
private static Image GenerateQRCode(byte[] data, int ppm = 4)
|
2017-01-12 01:55:42 +00:00
|
|
|
|
{
|
|
|
|
|
using (var generator = new QRCodeGenerator())
|
|
|
|
|
using (var qr_data = generator.CreateQRCode(data))
|
|
|
|
|
using (var qr_code = new QRCode(qr_data))
|
|
|
|
|
return qr_code.GetGraphic(ppm);
|
|
|
|
|
}
|
2017-03-11 04:35:18 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
public static string GetQRServer(int format)
|
2017-03-11 04:35:18 +00:00
|
|
|
|
{
|
|
|
|
|
switch (format)
|
|
|
|
|
{
|
|
|
|
|
case 6:
|
|
|
|
|
return QR6Path;
|
|
|
|
|
default:
|
2017-06-18 01:37:19 +00:00
|
|
|
|
return QR6PathBad;
|
2017-03-11 04:35:18 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2015-02-25 04:10:47 +00:00
|
|
|
|
}
|
2017-05-15 20:07:07 +00:00
|
|
|
|
}
|