QRData.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. using FastReport.Utils;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.Linq;
  6. using System.Security.Policy;
  7. using System.Text;
  8. using System.Text.RegularExpressions;
  9. namespace FastReport.Barcode.QRCode
  10. {
  11. abstract class QRData
  12. {
  13. public string data;
  14. public QRData() { }
  15. public QRData(string data)
  16. {
  17. Unpack(data);
  18. }
  19. public virtual string Pack()
  20. {
  21. return data;
  22. }
  23. public virtual void Unpack(string data)
  24. {
  25. this.data = data;
  26. }
  27. public static QRData Parse(string data)
  28. {
  29. if (data.StartsWith("BEGIN:VCARD"))
  30. return new QRvCard(data);
  31. else if (data.StartsWith("MATMSG:"))
  32. return new QREmailMessage(data);
  33. else if (data.StartsWith("geo:"))
  34. return new QRGeo(data);
  35. else if (data.StartsWith("SMSTO:"))
  36. return new QRSMS(data);
  37. else if (data.StartsWith("tel:"))
  38. return new QRCall(data);
  39. else if (data.StartsWith("BEGIN:VEVENT"))
  40. return new QREvent(data);
  41. else if (data.StartsWith("WIFI:"))
  42. return new QRWifi(data);
  43. else if (Uri.IsWellFormedUriString(data, UriKind.Absolute))
  44. return new QRURI(data);
  45. else if (Regex.IsMatch(data, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"))
  46. return new QREmailAddress(data);
  47. else if (data.StartsWith("SPC"))
  48. return new QRSwiss(data);
  49. else if (data.StartsWith("ST"))
  50. return new QRSberBank(data);
  51. else
  52. return new QRText(data);
  53. }
  54. }
  55. class QRText : QRData
  56. {
  57. public QRText() : base() { }
  58. public QRText(string data) : base(data) { }
  59. }
  60. class QRvCard : QRData
  61. {
  62. public string firstName;
  63. public string lastName;
  64. public string street;
  65. public string zipCode;
  66. public string city;
  67. public string country;
  68. public string fn_card;
  69. public string title;
  70. public string org;
  71. public string url;
  72. public string tel_cell;
  73. public string tel_work_voice;
  74. public string tel_home_voice;
  75. public string email_home_internet;
  76. public string email_work_internet;
  77. public QRvCard() : base() { }
  78. public QRvCard(string data) : base(data) { }
  79. public override string Pack()
  80. {
  81. StringBuilder data = new StringBuilder("BEGIN:VCARD\nVERSION:2.1\n");
  82. if ((firstName != null && firstName != "") ||
  83. (lastName != null && lastName != ""))
  84. {
  85. data.Append("FN:" + firstName + " " + lastName + "\n");
  86. data.Append("N:" + lastName + ";" + firstName + "\n");
  87. }
  88. data.Append(Append("TITLE:", title));
  89. data.Append(Append("ORG:", org));
  90. data.Append(Append("URL:", url));
  91. data.Append(Append("TEL;CELL:", tel_cell));
  92. data.Append(Append("TEL;WORK;VOICE:", tel_work_voice));
  93. data.Append(Append("TEL;HOME;VOICE:", tel_home_voice));
  94. data.Append(Append("EMAIL;HOME;INTERNET:", email_home_internet));
  95. data.Append(Append("EMAIL;WORK;INTERNET:", email_work_internet));
  96. if ((street != null && street != "") ||
  97. (zipCode != null && zipCode != "") ||
  98. (city != null && city != "") ||
  99. (country != null && country != ""))
  100. {
  101. data.Append("ADR:;;" + street + ";" + city + ";;" + zipCode + ";" + country + "\n");
  102. }
  103. data.Append("END:VCARD");
  104. return data.ToString();
  105. }
  106. private string Append(string name, string data)
  107. {
  108. if (data != null && data != "")
  109. return name + data + "\n";
  110. return "";
  111. }
  112. public override void Unpack(string data)
  113. {
  114. string[] lines = data.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
  115. foreach (string line in lines)
  116. {
  117. string[] s = line.Split(new string[] { ":" }, 2, StringSplitOptions.None);
  118. switch (s[0])
  119. {
  120. case "FN":
  121. fn_card = s[1];
  122. break;
  123. case "N":
  124. string[] n = s[1].Split(new string[] { ";" }, StringSplitOptions.None);
  125. lastName = n[0];
  126. firstName = n[1];
  127. break;
  128. case "TITLE":
  129. title = s[1];
  130. break;
  131. case "ORG":
  132. org = s[1];
  133. break;
  134. case "URL":
  135. url = s[1];
  136. break;
  137. case "TEL;CELL":
  138. tel_cell = s[1];
  139. break;
  140. case "TEL;WORK;VOICE":
  141. tel_work_voice = s[1];
  142. break;
  143. case "TEL;HOME;VOICE":
  144. tel_home_voice = s[1];
  145. break;
  146. case "EMAIL;HOME;INTERNET":
  147. email_home_internet = s[1];
  148. break;
  149. case "EMAIL;WORK;INTERNET":
  150. email_work_internet = s[1];
  151. break;
  152. case "ADR":
  153. string[] adr = s[1].Split(new string[] { ";" }, StringSplitOptions.None);
  154. street = adr[2];
  155. city = adr[3];
  156. zipCode = adr[5];
  157. country = adr[6];
  158. break;
  159. }
  160. }
  161. }
  162. }
  163. class QRURI : QRData
  164. {
  165. public QRURI() : base() { }
  166. public QRURI(string data) : base(data) { }
  167. }
  168. class QREmailAddress : QRData
  169. {
  170. public QREmailAddress() : base() { }
  171. public QREmailAddress(string data) : base(data) { }
  172. }
  173. class QREmailMessage : QRData
  174. {
  175. public string msg_to;
  176. public string msg_sub;
  177. public string msg_body;
  178. public QREmailMessage() : base() { }
  179. public QREmailMessage(string data) : base(data) { }
  180. public override string Pack()
  181. {
  182. return "MATMSG:TO:" + msg_to + ";SUB:" + msg_sub + ";BODY:" + msg_body + ";;";
  183. }
  184. public override void Unpack(string data)
  185. {
  186. string[] s = data.Split(new string[] { "MATMSG:TO:", ";SUB:", ";BODY:" }, 4, StringSplitOptions.None);
  187. msg_to = s[1];
  188. msg_sub = s[2];
  189. msg_body = s[3].Remove(s[3].Length - 2, 2);
  190. }
  191. }
  192. class QRSberBank : QRData
  193. {
  194. char Separator = '|';
  195. private string FormatIdentifier = "ST";
  196. public string VersionStandart = "0001";
  197. public string Encoding = "2";
  198. #region necessary payment details
  199. public string Name;
  200. public string PersonalAcc;
  201. public string BankName;
  202. public string BIC;
  203. public string CorrespAcc;
  204. #endregion
  205. #region Additional payment info
  206. public string Sum;
  207. public string Purpose;
  208. public string PayeeINNB;
  209. public string PayerINN;
  210. public string DrawerStatus;
  211. public string KPP;
  212. public string CBC;
  213. public string OKTMO;
  214. public string PaytReason;
  215. public string TaxPeriod;
  216. public string DocNo;
  217. public DateTime DocDate;
  218. public string TaxPaytKind;
  219. #endregion
  220. #region Another additional payment info
  221. public string LastName;
  222. public string FirstName;
  223. public string MiddleName;
  224. public string PayerAddress;
  225. public string PersonalAccount;
  226. public string DocIdx;
  227. public string PensAcc;
  228. public string Contract;
  229. public string PersAccp;
  230. public string Flat;
  231. public string Phone;
  232. public string PayerIdType;
  233. public string PayerIdNum;
  234. public string ChildFio;
  235. public DateTime BirthDate;
  236. public DateTime PaymTerm;
  237. public string PaymPeriod;
  238. public string Category;
  239. public string ServiceName;
  240. public string CounterId;
  241. public string CounterVal;
  242. public string QuittId;
  243. public DateTime QuittDate;
  244. public string InstNum;
  245. public string ClassNum;
  246. public string SpecFio;
  247. public string AddAmount;
  248. public string RuleId;
  249. public string ExecId;
  250. public string RegType;
  251. public string UIN;
  252. public string TechCode; //specify numbers somewhere
  253. #endregion
  254. public QRSberBank() : base() { }
  255. public QRSberBank(string data) : base(data) { }
  256. public override string Pack()
  257. {
  258. string result = FormatIdentifier;
  259. result += VersionStandart;
  260. result += Encoding;
  261. result += Separator + "Name=" + Name;
  262. result += Separator + "PersonalAcc=" + PersonalAcc;
  263. result += Separator + "BankName=" + BankName;
  264. result += Separator + "BIC=" + BIC;
  265. result += Separator + "CorrespAcc=" + CorrespAcc;
  266. if (!String.IsNullOrWhiteSpace(Sum)) result += Separator + "Sum=" + Sum;
  267. if (!String.IsNullOrWhiteSpace(Purpose)) result += Separator + "Purpose=" + Purpose;
  268. if (!String.IsNullOrWhiteSpace(PayeeINNB)) result += Separator + "PayeeINN=" + PayeeINNB;
  269. if (!String.IsNullOrWhiteSpace(PayerINN)) result += Separator + "PayerINN=" + PayerINN;
  270. if (!String.IsNullOrWhiteSpace(DrawerStatus)) result += Separator + "DrawerStatus=" + DrawerStatus;
  271. if (!String.IsNullOrWhiteSpace(KPP)) result += Separator + "KPP=" + KPP;
  272. if (!String.IsNullOrWhiteSpace(CBC)) result += Separator + "CBC=" + CBC;
  273. if (!String.IsNullOrWhiteSpace(OKTMO)) result += Separator + "OKTMO=" + OKTMO;
  274. if (!String.IsNullOrWhiteSpace(PaytReason)) result += Separator + "PaytReason=" + PaytReason;
  275. if (!String.IsNullOrWhiteSpace(TaxPeriod)) result += Separator + "TaxPeriod=" + TaxPeriod;
  276. if (!String.IsNullOrWhiteSpace(DocNo)) result += Separator + "DocNo=" + DocNo;
  277. if (DocDate != DateTime.MinValue)
  278. {
  279. result += Separator + "DocDate=" + DocDate.ToString("MM.dd.yyyy");
  280. }
  281. if (!String.IsNullOrWhiteSpace(TaxPaytKind)) result += Separator + "TaxPaytKind=" + TaxPaytKind;
  282. if (!String.IsNullOrWhiteSpace(LastName)) result += Separator + "LastName=" + LastName;
  283. if (!String.IsNullOrWhiteSpace(FirstName)) result += Separator + "FirstName=" + FirstName;
  284. if (!String.IsNullOrWhiteSpace(MiddleName)) result += Separator + "MiddleName=" + MiddleName;
  285. if (!String.IsNullOrWhiteSpace(PayerAddress)) result += Separator + "PayerAddress=" + PayerAddress;
  286. if (!String.IsNullOrWhiteSpace(PersonalAccount)) result += Separator + "PersonalAccount=" + PersonalAccount;
  287. if (!String.IsNullOrWhiteSpace(DocIdx)) result += Separator + "DocIdx=" + DocIdx;
  288. if (!String.IsNullOrWhiteSpace(PensAcc)) result += Separator + "PensAcc=" + PensAcc;
  289. if (!String.IsNullOrWhiteSpace(Contract)) result += Separator + "Contract=" + Contract;
  290. if (!String.IsNullOrWhiteSpace(PersAccp)) result += Separator + "PersAcc=" + PersAccp;
  291. if (!String.IsNullOrWhiteSpace(Flat)) result += Separator + "Flat=" + Flat;
  292. if (!String.IsNullOrWhiteSpace(Phone)) result += Separator + "Phone=" + Phone;
  293. if (!String.IsNullOrWhiteSpace(PayerIdType)) result += Separator + "PayerIdType=" + PayerIdType;
  294. if (!String.IsNullOrWhiteSpace(PayerIdNum)) result += Separator + "PayerIdNum=" + PayerIdNum;
  295. if (!String.IsNullOrWhiteSpace(ChildFio)) result += Separator + "ChildFio=" + ChildFio;
  296. if (BirthDate != DateTime.MinValue)
  297. {
  298. result += Separator + "BirthDate=" + BirthDate.ToString("MM.dd.yyyy");
  299. }
  300. if (PaymTerm != DateTime.MinValue)
  301. {
  302. result += Separator + "PaymTerm=" + PaymTerm.ToString("MM.dd.yyyy");
  303. }
  304. if (!String.IsNullOrWhiteSpace(PaymPeriod)) result += Separator + "PaymPeriod=" + PaymPeriod;
  305. if (!String.IsNullOrWhiteSpace(Category)) result += Separator + "Category=" + Category;
  306. if (!String.IsNullOrWhiteSpace(ServiceName)) result += Separator + "ServiceName=" + ServiceName;
  307. if (!String.IsNullOrWhiteSpace(CounterId)) result += Separator + "CounterId=" + CounterId;
  308. if (!String.IsNullOrWhiteSpace(CounterVal)) result += Separator + "CounterVal=" + CounterVal;
  309. if (!String.IsNullOrWhiteSpace(QuittId)) result += Separator + "QuittId=" + QuittId;
  310. if (QuittDate != DateTime.MinValue)
  311. {
  312. result += Separator + "QuittDate=" + QuittDate.ToString("MM.dd.yyyy");
  313. }
  314. if (!String.IsNullOrWhiteSpace(InstNum)) result += Separator + "InstNum=" + InstNum;
  315. if (!String.IsNullOrWhiteSpace(ClassNum)) result += Separator + "ClassNum=" + ClassNum;
  316. if (!String.IsNullOrWhiteSpace(SpecFio)) result += Separator + "SpecFio=" + SpecFio;
  317. if (!String.IsNullOrWhiteSpace(AddAmount)) result += Separator + "AddAmount=" + AddAmount;
  318. if (!String.IsNullOrWhiteSpace(RuleId)) result += Separator + "RuleId=" + RuleId;
  319. if (!String.IsNullOrWhiteSpace(ExecId)) result += Separator + "ExecId=" + ExecId;
  320. if (!String.IsNullOrWhiteSpace(RegType)) result += Separator + "RegType=" + RegType;
  321. if (!String.IsNullOrWhiteSpace(UIN)) result += Separator + "UIN=" + UIN;
  322. if (!String.IsNullOrWhiteSpace(TechCode)) result += Separator + "TechCode=" + TechCode;
  323. return result;
  324. }
  325. public override void Unpack(string data)
  326. {
  327. data = RetrieveServiceData(data);
  328. string[] splitedString = data.Split(Separator);
  329. foreach (string str in splitedString)
  330. {
  331. string[] splitedStr = str.Split(new string[] { "=" }, 2, StringSplitOptions.RemoveEmptyEntries);
  332. switch (splitedStr[0])
  333. {
  334. case "Name":
  335. Name = splitedStr[1];
  336. break;
  337. case "PersonalAcc":
  338. PersonalAcc = splitedStr[1];
  339. break;
  340. case "BankName":
  341. BankName = splitedStr[1];
  342. break;
  343. case "BIC":
  344. BIC = splitedStr[1];
  345. break;
  346. case "CorrespAcc":
  347. CorrespAcc = splitedStr[1];
  348. break;
  349. case "Sum":
  350. Sum = splitedStr[1];
  351. break;
  352. case "Purpose":
  353. Purpose = splitedStr[1];
  354. break;
  355. case "PayeeINN":
  356. PayeeINNB = splitedStr[1];
  357. break;
  358. case "PayerINN":
  359. PayerINN = splitedStr[1];
  360. break;
  361. case "DrawerStatus":
  362. DrawerStatus = splitedStr[1];
  363. break;
  364. case "KPP":
  365. KPP = splitedStr[1];
  366. break;
  367. case "CBC":
  368. CBC = splitedStr[1];
  369. break;
  370. case "OKTMO":
  371. OKTMO = splitedStr[1];
  372. break;
  373. case "PaytReason":
  374. PaytReason = splitedStr[1];
  375. break;
  376. case "TaxPeriod":
  377. TaxPeriod = splitedStr[1];
  378. break;
  379. case "DocNo":
  380. DocNo = splitedStr[1];
  381. break;
  382. case "DocDate":
  383. DocDate = DateTime.Parse(splitedStr[1]);
  384. break;
  385. case "TaxPaytKind":
  386. TaxPaytKind = splitedStr[1];
  387. break;
  388. case "LastName":
  389. LastName = splitedStr[1];
  390. break;
  391. case "FirstName":
  392. FirstName = splitedStr[1];
  393. break;
  394. case "MiddleName":
  395. MiddleName = splitedStr[1];
  396. break;
  397. case "PayerAddress":
  398. PayerAddress = splitedStr[1];
  399. break;
  400. case "PersonalAccount":
  401. PersonalAccount = splitedStr[1];
  402. break;
  403. case "DocIdx":
  404. DocIdx = splitedStr[1];
  405. break;
  406. case "PensAcc":
  407. PensAcc = splitedStr[1];
  408. break;
  409. case "PersAcc":
  410. PersAccp = splitedStr[1];
  411. break;
  412. case "Contract":
  413. Contract = splitedStr[1];
  414. break;
  415. case "Flat":
  416. Flat = splitedStr[1];
  417. break;
  418. case "Phone":
  419. Phone = splitedStr[1];
  420. break;
  421. case "PayerIdType":
  422. PayerIdType = splitedStr[1];
  423. break;
  424. case "PayerIdNum":
  425. PayerIdNum = splitedStr[1];
  426. break;
  427. case "ChildFio":
  428. ChildFio = splitedStr[1];
  429. break;
  430. case "BirthDate":
  431. BirthDate = DateTime.Parse(splitedStr[1]);
  432. break;
  433. case "PaymTerm":
  434. PaymTerm = DateTime.Parse(splitedStr[1]);
  435. break;
  436. case "PaymPeriod":
  437. PaymPeriod = splitedStr[1];
  438. break;
  439. case "Category":
  440. Category = splitedStr[1];
  441. break;
  442. case "ServiceName":
  443. ServiceName = splitedStr[1];
  444. break;
  445. case "CounterId":
  446. CounterId = splitedStr[1];
  447. break;
  448. case "CounterVal":
  449. CounterVal = splitedStr[1];
  450. break;
  451. case "QuittId":
  452. QuittId = splitedStr[1];
  453. break;
  454. case "QuittDate":
  455. QuittDate = DateTime.Parse(splitedStr[1]);
  456. break;
  457. case "InstNum":
  458. InstNum = splitedStr[1];
  459. break;
  460. case "ClassNum":
  461. ClassNum = splitedStr[1];
  462. break;
  463. case "SpecFio":
  464. SpecFio = splitedStr[1];
  465. break;
  466. case "AddAmount":
  467. AddAmount = splitedStr[1];
  468. break;
  469. case "RuleId":
  470. RuleId = splitedStr[1];
  471. break;
  472. case "ExecId":
  473. ExecId = splitedStr[1];
  474. break;
  475. case "RegType":
  476. RegType = splitedStr[1];
  477. break;
  478. case "UIN":
  479. UIN = splitedStr[1];
  480. break;
  481. case "TechCode":
  482. TechCode = splitedStr[1];
  483. break;
  484. }
  485. }
  486. }
  487. private string RetrieveServiceData(string data)
  488. {
  489. int firstSeparatorIndex = data.IndexOf(Separator);
  490. string retrievedData = data.Substring(0, firstSeparatorIndex);
  491. data = data.Substring(firstSeparatorIndex + 1);
  492. FormatIdentifier = retrievedData.Substring(0, 2);
  493. VersionStandart = retrievedData.Substring(2, 4);
  494. Encoding = retrievedData.Substring(6, 1);
  495. return data;
  496. }
  497. }
  498. class QRGeo : QRData
  499. {
  500. public string latitude;
  501. public string longitude;
  502. public string meters;
  503. public QRGeo() : base() { }
  504. public QRGeo(string data) : base(data) { }
  505. public override string Pack()
  506. {
  507. return "geo:" + latitude + "," + longitude + "," + meters;
  508. }
  509. public override void Unpack(string data)
  510. {
  511. string[] s = data.Split(new string[] { "geo:", "," }, 4, StringSplitOptions.None);
  512. latitude = s[1];
  513. longitude = s[2];
  514. meters = s[3];
  515. }
  516. }
  517. class QRSMS : QRData
  518. {
  519. public string sms_to;
  520. public string sms_text;
  521. public QRSMS() : base() { }
  522. public QRSMS(string data) : base(data) { }
  523. public override string Pack()
  524. {
  525. return "SMSTO:" + sms_to + ":" + sms_text;
  526. }
  527. public override void Unpack(string data)
  528. {
  529. string[] s = data.Split(new string[] { "SMSTO:", ":" }, StringSplitOptions.None);
  530. sms_to = s[1];
  531. sms_text = s[2];
  532. }
  533. }
  534. class QRCall : QRData
  535. {
  536. public string tel;
  537. public QRCall() : base() { }
  538. public QRCall(string data) : base(data) { }
  539. public override string Pack()
  540. {
  541. return "tel:" + tel;
  542. }
  543. public override void Unpack(string data)
  544. {
  545. tel = data.Remove(0, 4);
  546. }
  547. }
  548. class QREvent : QRData
  549. {
  550. public string summary;
  551. public DateTime dtStart;
  552. public DateTime dtEnd;
  553. public QREvent() : base() { }
  554. public QREvent(string data) : base(data) { }
  555. public override string Pack()
  556. {
  557. return "BEGIN:VEVENT\nSUMMARY:" + summary +
  558. "\nDTSTART:" + dtStart.Year.ToString("D4") +
  559. dtStart.Month.ToString("D2") +
  560. dtStart.Day.ToString("D2") + "T" +
  561. dtStart.Hour.ToString("D2") +
  562. dtStart.Minute.ToString("D2") +
  563. dtStart.Second.ToString("D2") + "Z" +
  564. "\nDTEND:" + dtEnd.Year.ToString("D4") +
  565. dtEnd.Month.ToString("D2") +
  566. dtEnd.Day.ToString("D2") + "T" +
  567. dtEnd.Hour.ToString("D2") +
  568. dtEnd.Minute.ToString("D2") +
  569. dtEnd.Second.ToString("D2") + "Z" +
  570. "\nEND:VEVENT";
  571. }
  572. public override void Unpack(string data)
  573. {
  574. string[] lines = data.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
  575. string From = "";
  576. string To = "";
  577. foreach (string line in lines)
  578. {
  579. string[] attr = line.Split(new string[] { ":" }, 2, StringSplitOptions.None);
  580. switch (attr[0])
  581. {
  582. case "SUMMARY":
  583. summary = attr[1];
  584. break;
  585. case "DTSTART":
  586. From = attr[1];
  587. break;
  588. case "DTEND":
  589. To = attr[1];
  590. break;
  591. }
  592. }
  593. dtStart = new DateTime(int.Parse(From.Substring(0, 4)),
  594. int.Parse(From.Substring(4, 2)),
  595. int.Parse(From.Substring(6, 2)),
  596. int.Parse(From.Substring(9, 2)),
  597. int.Parse(From.Substring(11, 2)),
  598. int.Parse(From.Substring(13, 2)));
  599. dtEnd = new DateTime(int.Parse(To.Substring(0, 4)),
  600. int.Parse(To.Substring(4, 2)),
  601. int.Parse(To.Substring(6, 2)),
  602. int.Parse(To.Substring(9, 2)),
  603. int.Parse(To.Substring(11, 2)),
  604. int.Parse(To.Substring(13, 2)));
  605. }
  606. }
  607. class QRWifi : QRData
  608. {
  609. public string encryption;
  610. public string networkName;
  611. public string password;
  612. public bool hidden;
  613. public QRWifi() : base() { }
  614. public QRWifi(string data) : base(data) { }
  615. public override string Pack()
  616. {
  617. return "WIFI:T:" + (encryption == "unencrypted" ? "nopass" : encryption) +
  618. ";S:" + networkName + ";P:" + (encryption == "unencrypted" ? "" : password) +
  619. (hidden ? ";H:true;" : ";;");
  620. }
  621. public override void Unpack(string data)
  622. {
  623. string[] s = data.Split(new string[] { "WIFI:T:", ";S:", ";P:", ";H:", ";;" }, StringSplitOptions.None);
  624. encryption = s[1] == "nopass" ? "unencrypted" : s[1];
  625. networkName = s[2];
  626. password = s[3];
  627. hidden = s[4] == "true;" ? true : false;
  628. }
  629. }
  630. class QRSwiss : QRData
  631. {
  632. private string br = "\r\n";
  633. private string alternativeProcedure1, alternativeProcedure2;
  634. private Iban iban;
  635. private string amount;
  636. private Contact creditor, ultimateCreditor, debitor;
  637. private string currency;
  638. private Reference reference;
  639. private AdditionalInformation additionalInformation;
  640. private MyRes res;
  641. public Iban _Iban { get { return iban; } set { iban = value; } }
  642. public Contact Creditor { get { return creditor; } set { creditor = value; } }
  643. public Contact Debitor { get { return debitor; } set { debitor = value; } }
  644. public string Amount { get { return amount; } }
  645. public string _Currency { get { return currency; } set { currency = value; } }
  646. public Reference _Reference { get { return reference; } set { reference = value; } }
  647. public AdditionalInformation _AdditionalInformation { get { return additionalInformation; } set { additionalInformation = value; } }
  648. public string AlternativeProcedure1 { get { return alternativeProcedure1; } set { alternativeProcedure1 = value; } }
  649. public string AlternativeProcedure2 { get { return alternativeProcedure2; } set { alternativeProcedure2 = value; } }
  650. //public QRSwiss() : base() { }
  651. public QRSwiss(string data) : base(data)
  652. {
  653. res = new MyRes("Messages,Swiss");
  654. }
  655. public QRSwiss(QRSwissParameters parameters)
  656. {
  657. res = new MyRes("Messages,Swiss");
  658. if (parameters.Iban == null)
  659. throw new SwissQrCodeException(res.Get("SwissNullIban"));
  660. if (parameters.Creditor == null)
  661. throw new SwissQrCodeException(res.Get("SwissNullCreditor"));
  662. if (parameters.Reference == null)
  663. throw new SwissQrCodeException(res.Get("SwissNullReference"));
  664. if (parameters.Currency == null)
  665. throw new SwissQrCodeException(res.Get("SwissNullCurrency"));
  666. this.iban = parameters.Iban;
  667. this.creditor = parameters.Creditor;
  668. this.additionalInformation = parameters.AdditionalInformation != null ? parameters.AdditionalInformation : new AdditionalInformation(null, null);
  669. if (!String.IsNullOrEmpty(parameters.Amount))
  670. if (!parameters.Amount.StartsWith("[") || !parameters.Amount.EndsWith("]"))
  671. {
  672. //Amount has to use . as decimal separator in any case. See https://www.paymentstandards.ch/dam/downloads/ig-qr-bill-en.pdf page 27.
  673. decimal.TryParse(parameters.Amount, NumberStyles.Number, CultureInfo.InvariantCulture, out decimal decAmount);
  674. decimal roundedAmount = decimal.Round(decAmount, 2, MidpointRounding.AwayFromZero);
  675. // if the parameters.Amount contains "0", or "0.", or ".0"
  676. if (Regex.IsMatch(parameters.Amount, @"^0(\.0+)?$"))
  677. {
  678. roundedAmount = 0m;
  679. }
  680. else
  681. {
  682. // If the rounded number is less than or equal to 0, then set it to the minimum allowed value
  683. if (roundedAmount <= 0)
  684. {
  685. roundedAmount = 0.01m;
  686. }
  687. // If the rounded number is greater than 999999999.99, then set it to the maximum allowed value
  688. if (roundedAmount > 999999999.99m)
  689. {
  690. roundedAmount = 999999999.99m;
  691. }
  692. }
  693. parameters.Amount = roundedAmount.ToString("0.00", CultureInfo.InvariantCulture);
  694. // in theory, this check is no longer needed
  695. // if (parameters.Amount.Length > 12)
  696. // throw new SwissQrCodeException(res.Get("SwissAmountLength"));
  697. }
  698. this.amount = parameters.Amount;
  699. switch (parameters.Currency)
  700. {
  701. case nameof(Currency.EUR):
  702. parameters.Currency = Currency.EUR.ToString();
  703. break;
  704. case nameof(Currency.CHF):
  705. parameters.Currency = Currency.CHF.ToString();
  706. break;
  707. default:
  708. if (!parameters.Currency.StartsWith("[") || !parameters.Currency.EndsWith("]"))
  709. parameters.Currency = Currency.EUR.ToString();
  710. break;
  711. }
  712. this.currency = parameters.Currency;
  713. this.debitor = parameters.Debitor;
  714. if (iban.IsQrIban && parameters.Reference.RefType != Reference.ReferenceType.QRR)
  715. throw new SwissQrCodeException(res.Get("SwissQRIban"));
  716. if (!iban.IsQrIban && parameters.Reference.RefType == Reference.ReferenceType.QRR)
  717. throw new SwissQrCodeException(res.Get("SwissNonQRIban"));
  718. this.reference = parameters.Reference;
  719. if (parameters.AlternativeProcedure1 != null && parameters.AlternativeProcedure1.Length > 100)
  720. throw new SwissQrCodeException(res.Get("SwissAltProcedureLength"));
  721. this.alternativeProcedure1 = parameters.AlternativeProcedure1;
  722. if (parameters.AlternativeProcedure2 != null && parameters.AlternativeProcedure2.Length > 100)
  723. throw new SwissQrCodeException(res.Get("SwissAltProcedureLength"));
  724. this.alternativeProcedure2 = parameters.AlternativeProcedure2;
  725. }
  726. public override void Unpack(string data)
  727. {
  728. string[] separators = { "\r\n", "\n" };
  729. string[] datas = data.Split(separators, StringSplitOptions.None);
  730. int counter = 3;
  731. this.iban = new Iban(datas[counter]);
  732. counter++;
  733. string infoString = "";
  734. for (int i = counter; i < counter + 7; i++)
  735. {
  736. infoString += datas[i] + '\r';
  737. }
  738. counter += 7;
  739. this.creditor = new Contact(infoString);
  740. if (datas[counter] != String.Empty)
  741. {
  742. infoString = String.Empty;
  743. for (int i = counter; i < counter + 7; i++)
  744. {
  745. infoString += datas[i] + '\r';
  746. }
  747. this.ultimateCreditor = new Contact(infoString);
  748. }
  749. counter += 7;
  750. if (!datas[counter].StartsWith("[") || !datas[counter].EndsWith("]"))
  751. {
  752. //Amount has to use . as decimal separator in any case. See https://www.paymentstandards.ch/dam/downloads/ig-qr-bill-en.pdf page 27.
  753. string invariantSeparator = CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator;
  754. string clearQRSwissAmount = datas[counter].Replace(",", invariantSeparator).Replace("/", invariantSeparator);
  755. decimal.TryParse(clearQRSwissAmount, NumberStyles.Number, CultureInfo.InvariantCulture, out decimal decAmount);
  756. amount = datas[counter] == String.Empty ? amount = null : decAmount.ToString(CultureInfo.InvariantCulture);
  757. }
  758. else amount = datas[counter] == String.Empty ? amount = null : datas[counter];
  759. counter++;
  760. switch (datas[counter])
  761. {
  762. case nameof(Currency.EUR):
  763. this.currency = Currency.EUR.ToString();
  764. break;
  765. case nameof(Currency.CHF):
  766. this.currency = Currency.CHF.ToString();
  767. break;
  768. default:
  769. if (datas[counter].StartsWith("[") && datas[counter].EndsWith("]"))
  770. currency = datas[counter];
  771. else
  772. currency = Currency.EUR.ToString();
  773. break;
  774. }
  775. counter++;
  776. if (datas[counter] != String.Empty)
  777. {
  778. infoString = String.Empty;
  779. for (int i = counter; i < counter + 7; i++)
  780. {
  781. infoString += datas[i] + '\r';
  782. }
  783. this.debitor = new Contact(infoString);
  784. }
  785. counter += 7;
  786. infoString = String.Empty;
  787. for (int i = counter; i < counter + 2; i++)
  788. {
  789. infoString += datas[i] + '\r';
  790. }
  791. this.reference = new Reference(infoString);
  792. if (reference.RefType == Reference.ReferenceType.QRR)
  793. iban.TypeIban = Iban.IbanType.QrIban;
  794. else
  795. iban.TypeIban = Iban.IbanType.Iban;
  796. if (!String.IsNullOrEmpty(reference.ReferenceText))
  797. {
  798. if (reference.ReferenceText.StartsWith("[") && reference.ReferenceText.EndsWith("]"))
  799. {
  800. if (reference.RefType == Reference.ReferenceType.QRR)
  801. reference._ReferenceTextType = Reference.ReferenceTextType.QrReference;
  802. else
  803. reference._ReferenceTextType = Reference.ReferenceTextType.CreditorReferenceIso11649;
  804. }
  805. else
  806. {
  807. if (reference.ChecksumMod10(reference.ReferenceText))
  808. reference._ReferenceTextType = Reference.ReferenceTextType.QrReference;
  809. else if (Regex.IsMatch(reference.ReferenceText, "^[a-zA-Z0-9 ]+$"))
  810. reference._ReferenceTextType = Reference.ReferenceTextType.CreditorReferenceIso11649;
  811. }
  812. }
  813. if (!iban._Iban.StartsWith("[") || !iban._Iban.EndsWith("]"))
  814. iban = new Iban(iban._Iban, iban.TypeIban);
  815. counter += 2;
  816. infoString = String.Empty;
  817. for (int i = counter; i < counter + 3; i++)
  818. {
  819. // this condition is necessary for the case when there are no more data after the EPD trailer, including empty lines
  820. if (i < datas.Length)
  821. infoString += datas[i] + '\r';
  822. }
  823. this.additionalInformation = new AdditionalInformation(infoString);
  824. counter += 3;
  825. if (datas.Length - 1 >= counter)
  826. {
  827. alternativeProcedure1 = datas[counter];
  828. }
  829. counter++;
  830. if (datas.Length - 1 >= counter)
  831. {
  832. alternativeProcedure2 = datas[counter];
  833. }
  834. }
  835. public override string Pack()
  836. {
  837. string SwissQrCodePayload = "SPC" + br; //QRType
  838. SwissQrCodePayload += "0200" + br; //Version
  839. SwissQrCodePayload += "1" + br; //Coding
  840. //CdtrInf "logical" element
  841. SwissQrCodePayload += iban.ToString() + br; //IBAN
  842. //Cdtr "logical" element
  843. SwissQrCodePayload += creditor.ToString();
  844. //UltmtCdtr "logical" element
  845. //Since version 2.0 ultimate creditor was marked as "for future use" and has to be delivered empty in any case!
  846. //SwissQrCodePayload += string.Concat(Enumerable.Repeat(br, 7).ToArray());
  847. for (int i = 0; i < 7; i++)
  848. {
  849. SwissQrCodePayload += br;
  850. }
  851. //CcyAmtDate "logical" element
  852. if (amount != null)
  853. SwissQrCodePayload += amount;
  854. else
  855. SwissQrCodePayload += string.Empty;
  856. SwissQrCodePayload += br;
  857. SwissQrCodePayload += currency + br; //Ccy
  858. //UltmtDbtr "logical" element
  859. if (debitor != null)
  860. SwissQrCodePayload += debitor.ToString();
  861. else
  862. for (int i = 0; i < 7; i++)
  863. {
  864. SwissQrCodePayload += br;
  865. }
  866. //RmtInf "logical" element
  867. SwissQrCodePayload += reference.RefType.ToString() + br; //Tp
  868. if (!string.IsNullOrEmpty(reference.ReferenceText))
  869. {
  870. if (reference.ReferenceText.StartsWith("[") && reference.ReferenceText.EndsWith("]"))
  871. SwissQrCodePayload += reference.ReferenceText + br;
  872. else
  873. SwissQrCodePayload += new string(reference.ReferenceText.Where(c => char.IsLetterOrDigit(c)).ToArray()).ToUpper() + br; //Ref
  874. }
  875. else
  876. {
  877. SwissQrCodePayload += string.Empty + br; //Ref
  878. }
  879. //AddInf "logical" element
  880. SwissQrCodePayload += (!string.IsNullOrEmpty(additionalInformation.UnstructureMessage) ? additionalInformation.UnstructureMessage : string.Empty) + br; //Ustrd
  881. SwissQrCodePayload += additionalInformation.Trailer + br; //Trailer
  882. SwissQrCodePayload += (!string.IsNullOrEmpty(additionalInformation.BillInformation) ? additionalInformation.BillInformation : string.Empty) + br; //StrdBkgInf
  883. //AltPmtInf "logical" element
  884. if (!string.IsNullOrEmpty(alternativeProcedure1))
  885. SwissQrCodePayload += alternativeProcedure1.Replace("\n", "") + br; //AltPmt
  886. if (!string.IsNullOrEmpty(alternativeProcedure2))
  887. SwissQrCodePayload += alternativeProcedure2.Replace("\n", "") + br; //AltPmt
  888. // removes all unnecessary \r\n at the end of the string,
  889. // according to https://www.six-group.com/dam/download/banking-services/standardization/qr-bill/ig-qr-bill-v2.3-en.pdf section 4.1.4 (page 31)
  890. SwissQrCodePayload = SwissQrCodePayload.TrimEnd(br.ToCharArray());
  891. return SwissQrCodePayload;
  892. }
  893. }
  894. }