Giancarlo Voci 7 years ago
parent
commit
64f644d5c5
48 changed files with 4960 additions and 4880 deletions
  1. 0 0
      README.md
  2. 1 1
      cfg/config.bin
  3. 12 12
      src/Modules/Blank/Blank.php
  4. 6 6
      src/Modules/Blank/Pages.php
  5. 12 11
      src/OpenMind/Admin/Admin.php
  6. 10 10
      src/OpenMind/Admin/Pages.php
  7. 17 17
      src/OpenMind/Admin/build.js
  8. 69 69
      src/OpenMind/Admin/ui/css/admin.scss
  9. 2 2
      src/OpenMind/Admin/ui/footer.tpl
  10. 6 6
      src/OpenMind/Admin/ui/header.tpl
  11. 20 20
      src/OpenMind/Admin/ui/js/admin.js
  12. 21 17
      src/OpenMind/Admin/ui/masterpage.tpl
  13. 156 156
      src/OpenMind/DataManager/CSVImporter.php
  14. 5 5
      src/OpenMind/FindBox/FindBox.php
  15. 176 176
      src/OpenMind/FindBox/FindBoxCoreSystem.php
  16. 180 180
      src/OpenMind/FindBox/FindBoxService.php
  17. 77 77
      src/OpenMind/FindBox/QueueCommand.php
  18. 131 131
      src/OpenMind/FindBox/SmartESL.php
  19. 59 59
      src/OpenMind/System/ErrorHandlers.php
  20. 57 57
      src/OpenMind/System/Notifications.php
  21. 108 108
      src/OpenMind/System/OMUtils.php
  22. 99 99
      src/OpenMind/System/PluginStrategy.php
  23. 57 56
      src/OpenMind/System/QueueSystem.php
  24. 31 31
      src/OpenMind/System/Soap.php
  25. 143 143
      src/OpenMind/System/System.php
  26. 39 39
      src/OpenMind/System/UserRoles.php
  27. 4 5
      src/OpenMind/Web/Controller.php
  28. 2870 2811
      src/Picqer/Barcode/BarcodeGenerator.php
  29. 35 35
      src/Picqer/Barcode/BarcodeGeneratorHTML.php
  30. 63 63
      src/Picqer/Barcode/BarcodeGeneratorJPG.php
  31. 62 62
      src/Picqer/Barcode/BarcodeGeneratorPNG.php
  32. 38 38
      src/Picqer/Barcode/BarcodeGeneratorSVG.php
  33. 3 1
      src/Picqer/Barcode/Exceptions/BarcodeException.php
  34. 3 1
      src/Picqer/Barcode/Exceptions/InvalidCharacterException.php
  35. 3 1
      src/Picqer/Barcode/Exceptions/InvalidCheckDigitException.php
  36. 3 1
      src/Picqer/Barcode/Exceptions/InvalidFormatException.php
  37. 3 1
      src/Picqer/Barcode/Exceptions/InvalidLengthException.php
  38. 3 1
      src/Picqer/Barcode/Exceptions/UnknownTypeException.php
  39. 6 5
      ui/bind.tpl
  40. 69 70
      ui/css/omlink.scss
  41. 2 2
      ui/errors.tpl
  42. 2 2
      ui/footer.tpl
  43. 6 6
      ui/header.tpl
  44. 179 179
      ui/images/svg/disegno.svg
  45. 71 71
      ui/js/omlink.js
  46. 6 6
      ui/login.tpl
  47. 12 8
      ui/masterpage.tpl
  48. 23 23
      ui/unbind.tpl

+ 0 - 0
TODO.txt → README.md


+ 1 - 1
cfg/config.bin

@@ -1 +1 @@
-eJx9kVFv2jAUhd8t+T9EPG2aGhwCtBuytBAMpA0xih3EVlVRCC5ETWLqJGwt4r/PgVV7myVL9tW9Pt85ftzlcpPk1RMEKxIyjwbYMgcmgsCJOPWpM8GdSqXdDgSu486JgQ0eRgSCyMNN1oVgQsbRDPcgIIFLJ14ww52IT2/u9MDcm819vTl+1goCgnsnNMXvQ6YEPp3qrBCfPn+xrYE9RAidz/otFuBO8Va95t/2sqpxLtMkb0+jg1Q1tm00HG03ZVIILIs8K1+0yHbTVEJhJWXdXg5JVWF5EGWRlVsIFs46Hvte8BBzb0FiRlxsI3Sth4SHP+IpDeOpE/kcW6h1s8K1ajQrBCNjmdR7CMYOI1Ho4+5VEwLmcRI4C4Lp4sa/VHw6o7EbMU4XJNTevv+dOZ+7OqSsSHai6uZyJ81DuYPAc2kQtzMR/19zU1/bWxQmcpHWxq99lu6NtKlqWQhlpLm2a4gy2eQa+QPgwvYBC8GjS0NiPm+eLpaU3DZpnckSgkvG1teeaQ3vTAuZVl8ncEl6gPp9+yqrjlqHE8YheBFv2EX/lmX1b/uoZ6PBrZ5rg/+pdu8vx3tFH8qAueWynL3bzckZijkL1qtj1eJooKkXTMZ0zUi48lyiuZhPyLL9Ia2sGf4AGu/CIA==
+eJx9kV1v2jAUhu8t+T9YXG2aGpwGaDdkaSEYSBtilA/EVlVRCC5ETWLmOPQD8d/nQKvdzZLl4yMfv895z8O2EOu0qB8hWNIgdJlPTKNvYAjsOGIes8ekU8us24HAsZ0ZRQRFQUwhiF3S5F0IxnQUT8k1BNR32Nj1p6QTR5OrW10wc6czT++IPGkFDsGdHRj8dZ9LTo5HlZf8y9dvltm3Bhjj00n/FfqkU77Vf4ofO1ErUogsLdpouBdSEcvCg+FmXaUlJ6Is8upZi2zWTc0lkUKo9rJP65qIPa/KvNpAMLdXychz/fskcuc0CalDLIwv+YBGwa9kwoJkYsdeREzcdrMkSjaaFYIhWqRqB8HIDmkceKR70YQgdCPq23NK2PzKO2c8NmWJE4cRm9NA9/bzo+Z06mqT8jLd8rpbiK0w9tUWAtdhftLWxNH/Hjfq8rxFCXnBM4Vednm2Q1lTK1FyibJCt4t4la4LjfwJcGb7hIXgwWEBNZ7Wj+eWpNg0mcpFBcHZY/P7tWEObg0TG2ZPO3B2uo97PesiKw9aJ6JhBMEzfyMO/rdMs3fTw9cW7t/outb433L7/ny4k+y+8kOnWlTTd6s52gM+C/3V8lC3OBpo4vrjEVuFNFi6DtVcoUfpop2QVsYX3UxUmxopgV7SXKEnIVHN9amnuhavOpaHPOOoEgqlhzQvLg5MA9uhyYIGLht/DBuCv3u+284=

+ 12 - 12
src/Modules/Blank/Blank.php

@@ -13,20 +13,20 @@ use OpenMind\System\UserRoles;
 
 class Blank extends PluginStrategy
 {
-  public function __construct()
-  {
-    $this->AddRoute('GET /helloworld', __NAMESPACE__ . '\Pages->HelloWorld');
+	public function __construct()
+	{
+		$this->AddRoute('GET /helloworld', __NAMESPACE__ . '\Pages->HelloWorld');
 
-    $this->AddMenuItem('Demo', [
-      'url' => 'helloworld',
-      'imgClass' => 'shadow p-3 rounded bg-white',
-      'image' => 'ui/images/demo.png',
-      'permissionName' => 'demo'
-    ]);
+		$this->AddMenuItem('Demo', [
+			'url' => 'helloworld',
+			'imgClass' => 'shadow p-3 rounded bg-white',
+			'image' => 'ui/images/demo.png',
+			'permissionName' => 'demo'
+		]);
 
-    $roles = new UserRoles();
-    $roles->add('demo');
-  }
+		$roles = new UserRoles();
+		$roles->add('demo');
+	}
 }
 
 /** @var Blank $Blank */

+ 6 - 6
src/Modules/Blank/Pages.php

@@ -12,10 +12,10 @@ use OpenMind\Web\Controller;
 
 class Pages extends Controller
 {
-  public function HelloWorld($f3)
-  {
-    $f3->set('MESSAGE', 'Hello World');
-    $f3->set('CONTENT', 'message.tpl');
-    echo \Template::instance()->render('masterpage.tpl');
-  }
+	public function HelloWorld($f3)
+	{
+		$f3->set('MESSAGE', 'Hello World');
+		$f3->set('CONTENT', 'message.tpl');
+		echo \Template::instance()->render('masterpage.tpl');
+	}
 }

+ 12 - 11
src/OpenMind/Admin/Admin.php

@@ -12,20 +12,21 @@ use OpenMind\System\UserRoles;
 
 class Admin extends PluginStrategy
 {
-  public function __construct()
-  {
-    $this->AddRoute('GET /admin', __NAMESPACE__ . '\Pages->Admin');
+	public function __construct()
+	{
+		$this->AddRoute('GET /admin', __NAMESPACE__ . '\Pages->Admin');
 
-    $this->AddRoute('GET /admin/eslstatus', __NAMESPACE__ . '\Pages->ESLStatus');
+		$this->AddRoute('GET /admin/eslstatus', __NAMESPACE__ . '\Pages->ESLStatus');
 
-    $this->AddMenuItem('ESLStatus', [
-      'url' => 'admin/ESLStatus',
-      'imgClass' => 'shadow p-3 rounded bg-white',
-      'permissionName' => 'admin'
-    ]);
+		$this->AddMenuItem('ESLStatus', [
+			'url' => 'admin/ESLStatus',
+			'imgClass' => 'shadow p-3 rounded bg-white',
+			'permissionName' => 'admin'
+		]);
 
-    $roles = new UserRoles();
-    $roles->add('admin');  }
+		$roles = new UserRoles();
+		$roles->add('admin');
+	}
 }
 
 /** @var \OpenMind\Admin $Admin */

+ 10 - 10
src/OpenMind/Admin/Pages.php

@@ -11,16 +11,16 @@ use OpenMind\Web\Controller;
 
 class Pages extends Controller
 {
-  public function __construct($f3)
-  {
-    parent::__construct($f3);
+	public function __construct($f3)
+	{
+		parent::__construct($f3);
 
-    // Set Admin F3 UI folder
-    $f3->set('UI', 'src/OpenMind/Admin/ui/');
-  }
+		// Set Admin F3 UI folder
+		$f3->set('UI', 'src/OpenMind/Admin/ui/');
+	}
 
-  public function Admin($f3)
-  {
-    echo \Template::instance()->render('masterpage.tpl');
-  }
+	public function Admin($f3)
+	{
+		echo \Template::instance()->render('masterpage.tpl');
+	}
 }

+ 17 - 17
src/OpenMind/Admin/build.js

@@ -5,19 +5,19 @@ const {writeFileSync} = require('fs');
 
 // The Libraries to join in minified files
 const libList = [
-  `${MODULES_PATH}/jquery/dist/jquery.min.js`,
-  `${MODULES_PATH}/bootstrap/dist/js/bootstrap.bundle.min.js`
+	`${MODULES_PATH}/jquery/dist/jquery.min.js`,
+	`${MODULES_PATH}/bootstrap/dist/js/bootstrap.bundle.min.js`
 ];
 
 // The css files to minify
 const cssList = [
-  `${MODULES_PATH}/bootstrap/dist/css/bootstrap.min.css`,
-  "ui/css/admin.css"
+	`${MODULES_PATH}/bootstrap/dist/css/bootstrap.min.css`,
+	"ui/css/admin.css"
 ];
 
 // The javascript files to minify
 const jsList = [
-  "ui/js/admin.js"
+	"ui/js/admin.js"
 ];
 
 /**
@@ -29,22 +29,22 @@ let buffer = sass.renderSync({file: 'ui/css/admin.scss'});
 writeFileSync('ui/css/admin.css', buffer.css);
 
 compressor.minify({
-    compressor: 'clean-css',
-    input: cssList,
-    output: 'ui/bundle.css'
-  }
+		compressor: 'clean-css',
+		input: cssList,
+		output: 'ui/bundle.css'
+	}
 );
 
 compressor.minify({
-    compressor: 'uglify-es',
-    input: jsList,
-    output: 'ui/js/admin.min.js'
-  }
+		compressor: 'uglify-es',
+		input: jsList,
+		output: 'ui/js/admin.min.js'
+	}
 );
 
 compressor.minify({
-    compressor: 'no-compress',
-    input: [].concat(libList, ["ui/js/admin.min.js"]),
-    output: 'ui/bundle.js'
-  }
+		compressor: 'no-compress',
+		input: [].concat(libList, ["ui/js/admin.min.js"]),
+		output: 'ui/bundle.js'
+	}
 );

+ 69 - 69
src/OpenMind/Admin/ui/css/admin.scss

@@ -27,41 +27,41 @@ $inputColor: white;
 $placeholderColor: gray !important;
 
 .navbar.fixed-bottom {
-  color: white;
+	color: white;
 }
 
 html, body {
-  height: 100%;
+	height: 100%;
 }
 
 body {
-  background-color: $mainColor !important;
-  color: $textColor !important;
-  font-family: 'Roboto';
+	background-color: $mainColor !important;
+	color: $textColor !important;
+	font-family: 'Roboto';
 }
 
 /* latin */
 @font-face {
-  font-family: 'Roboto';
-  font-style: normal;
-  font-weight: 400;
-  src: local('Roboto'), local('Roboto-Regular'), url('ui/fonts/Roboto-Regular.ttf') format('truetype');
-  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+	font-family: 'Roboto';
+	font-style: normal;
+	font-weight: 400;
+	src: local('Roboto'), local('Roboto-Regular'), url('ui/fonts/Roboto-Regular.ttf') format('truetype');
+	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
 }
 
 .error_body:before {
-  content: "";
-  position: absolute;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  background: url('ui/images/error_bg.png');
-  background-size: cover;
+	content: "";
+	position: absolute;
+	left: 0;
+	top: 0;
+	width: 100%;
+	height: 100%;
+	background: url('ui/images/error_bg.png');
+	background-size: cover;
 }
 
 .error_body .card {
-  opacity: 0.9;
+	opacity: 0.9;
 }
 
 /*
@@ -87,107 +87,107 @@ input:focus {
 }*/
 
 .form-control, .btn {
-  background-color: $inputBgColor !important;
-  color: $inputColor !important;
+	background-color: $inputBgColor !important;
+	color: $inputColor !important;
 }
 
 .form-control:focus, .btn:focus {
-  //  border-color: #c5ac0f !important;
-  background-color: lighten($inputBgColor, 8%) !important;
-  border-color: darken($inputBgColor, 10%) !important;
-  box-shadow: 0 0 10px $inputBgColor !important;
+	//  border-color: #c5ac0f !important;
+	background-color: lighten($inputBgColor, 8%) !important;
+	border-color: darken($inputBgColor, 10%) !important;
+	box-shadow: 0 0 10px $inputBgColor !important;
 }
 
 .form-control:disabled {
-  color: darken($inputColor, 10%) !important;
-  background-color: darken($inputBgColor, 8%) !important;
+	color: darken($inputColor, 10%) !important;
+	background-color: darken($inputBgColor, 8%) !important;
 }
 
 .debugborder {
-  border: 1px solid red !important;
+	border: 1px solid red !important;
 }
 
 .disablebutton {
-  opacity: 0.4;
+	opacity: 0.4;
 }
 
 .imgbuttonmenu {
-  max-height: 180px !important;
-  border-radius: 10px !important;
+	max-height: 180px !important;
+	border-radius: 10px !important;
 }
 
 .om-shadow {
-  filter: drop-shadow(0px 0.2em 5px $shadowColor);
+	filter: drop-shadow(0px 0.2em 5px $shadowColor);
 }
 
 input::placeholder {
-  color: $placeholderColor;
+	color: $placeholderColor;
 }
 
 input::-ms-input-placeholder {
-  color: $placeholderColor;
+	color: $placeholderColor;
 }
 
 .navbar {
-  background-color: $navbarsColor !important;
+	background-color: $navbarsColor !important;
 }
 
 .rounded {
-  border-radius: 15px !important;
+	border-radius: 15px !important;
 }
 
 @mixin prefix($property, $parameters...) {
-  @each $prefix in -webkit-, -moz-, -ms-, -o-, "" {
-    #{$prefix}#{$property}: $parameters;
-  }
+	@each $prefix in -webkit-, -moz-, -ms-, -o-, "" {
+		#{$prefix}#{$property}: $parameters;
+	}
 }
 
 // Blink Effect
 @keyframes blink {
-  0% {
-    @include prefix(opacity, 0.1);
-    // background-color: lighten(#28a745, 40%);
-  }
-  100% {
-    @include prefix(opacity, 1);
-    // background-color: darken(#28a745, 10%);
-  }
+	0% {
+		@include prefix(opacity, 0.1);
+		// background-color: lighten(#28a745, 40%);
+	}
+	100% {
+		@include prefix(opacity, 1);
+		// background-color: darken(#28a745, 10%);
+	}
 }
 
 @-webkit-keyframes blink {
-  0% {
-    @include prefix(opacity, 0.1);
-    // background-color: lighten(#28a745, 40%);
-  }
-  100% {
-    @include prefix(opacity, 1);
-    // background-color: darken(#28a745, 10%);
-  }
+	0% {
+		@include prefix(opacity, 0.1);
+		// background-color: lighten(#28a745, 40%);
+	}
+	100% {
+		@include prefix(opacity, 1);
+		// background-color: darken(#28a745, 10%);
+	}
 }
 
 .blink {
-  @include prefix(transition, all 0.1s ease-in-out);
-  @include prefix(animation, blink alternate 1s infinite ease-in-out);
+	@include prefix(transition, all 0.1s ease-in-out);
+	@include prefix(animation, blink alternate 1s infinite ease-in-out);
 }
 
 #sysmsgnum {
-  color: white;
-  background-color: red;
-  font-size: 40%;
-  position: absolute;
-  left: 15px;
-  bottom: 0;
+	color: white;
+	background-color: red;
+	font-size: 40%;
+	position: absolute;
+	left: 15px;
+	bottom: 0;
 }
 
 #notification_area {
-  padding-bottom: 0;
-  border-radius: 10px 10px
+	padding-bottom: 0;
+	border-radius: 10px 10px
 }
 
 #notification_area_deleteall {
-  background-color: #3380BD;
-  color: white;
-  border-radius: 0 0 10px 10px;
-  padding: 0;
+	background-color: #3380BD;
+	color: white;
+	border-radius: 0 0 10px 10px;
+	padding: 0;
 }
 

+ 2 - 2
src/OpenMind/Admin/ui/footer.tpl

@@ -1,11 +1,11 @@
 <nav class="navbar fixed-bottom navbar-expand navbar-dark">
 	<check if="{{ isset(@PREVPAGE) }}">
-		<a href="{{@PREVPAGE}}"><img class="navbar-brand" src="{{@BASEURL}}/ui/images/arrow-left.svg" height="50px"/></a>
+		<a href="{{@PREVPAGE}}"><img class="navbar-brand" height="50px" src="{{@BASEURL}}/ui/images/arrow-left.svg"/></a>
 	</check>
 	<div class="collapse navbar-collapse"></div>
 	<div class="navbar-brand">
 		<a href="{{@BASEURL}}">
-			<img src="{{@BASEURL}}/ui/images/om-link-logo.png" height="40"/>
+			<img height="40" src="{{@BASEURL}}/ui/images/om-link-logo.png"/>
 		</a>
 	</div>
 </nav>

+ 6 - 6
src/OpenMind/Admin/ui/header.tpl

@@ -1,6 +1,6 @@
 <nav class="navbar navbar-expand-sm navbar-dark bg-dark om-shadow">
 	<a href="{{@BASEURL}}/"><img class="img-fluid om-shadow navbar-brand customerlogo" src="{{@LOGO_CUSTOMER}}"/></a>
-	<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#headerMenu" aria-controls="headerMenu" aria-expanded="false" aria-label="Toggle navigation">
+	<button aria-controls="headerMenu" aria-expanded="false" aria-label="Toggle navigation" class="navbar-toggler" data-target="#headerMenu" data-toggle="collapse" type="button">
 		<span class="navbar-toggler-icon"></span>
 	</button>
 
@@ -9,7 +9,7 @@
 			<repeat group="{{@GLOBALMENU}}" key="{{ @ikey }}" value="{{@menuitem}}">
 				<check if="{{ !empty(@menuitem.url) }}">
 					<li class="nav-item">
-						<a role="button" class="nav-link btn btn-secondary" href="{{@BASEURL . '/' . @menuitem.url}}">{{@ikey}}</a>
+						<a class="nav-link btn btn-secondary" href="{{@BASEURL . '/' . @menuitem.url}}" role="button">{{@ikey}}</a>
 					</li>
 				</check>
 			</repeat>
@@ -17,13 +17,13 @@
 	</div>
 
 	<div class="ml-auto dropdown dropleft navbar-brand">
-		<a id="notification_area_button" class="disabled" href="javascript:void(0)" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="mr-3" style="position: relative">
+		<a aria-expanded="false" aria-haspopup="true" class="disabled" class="mr-3" data-toggle="dropdown" href="javascript:void(0)" id="notification_area_button" style="position: relative">
 			<img src="{{@BASEURL}}/ui/images/bell.png"/>
-			<span id="sysmsgnum" class="blink badge badge-light"></span>
+			<span class="blink badge badge-light" id="sysmsgnum"></span>
 		</a>
-		<div id="notification_area" class="dropdown-menu" aria-labelledby="dropdownMenuButton"></div>
+		<div aria-labelledby="dropdownMenuButton" class="dropdown-menu" id="notification_area"></div>
 	</div>
 	<div>
-		<a href="{{@BASEURL}}/logout"><img src="{{@ICON_LOGOUT}}" class="img-fluid om-shadow"/></a>
+		<a href="{{@BASEURL}}/logout"><img class="img-fluid om-shadow" src="{{@ICON_LOGOUT}}"/></a>
 	</div>
 </nav>

+ 20 - 20
src/OpenMind/Admin/ui/js/admin.js

@@ -7,36 +7,36 @@
  */
 
 var fetchHeaders = {
-  'Accept': 'text/html',
-  'Content-Type': 'text/html',
-  'X-Requested-With': 'XMLHttpRequest',
-  'Cache-Control': 'no-cache',
-  'Pragma': 'no-cache',
-  'Expires': '0'
+	'Accept': 'text/html',
+	'Content-Type': 'text/html',
+	'X-Requested-With': 'XMLHttpRequest',
+	'Cache-Control': 'no-cache',
+	'Pragma': 'no-cache',
+	'Expires': '0'
 };
 
 function SetupConfirmationDialog() {
-  $('.requestconfirm').on('click', function (ev) {
-    let confirmText = $(this).data('confirmtext');
-    if (!confirm(confirmText))
-      ev.preventDefault();
-  });
+	$('.requestconfirm').on('click', function (ev) {
+		let confirmText = $(this).data('confirmtext');
+		if (!confirm(confirmText))
+			ev.preventDefault();
+	});
 }
 
 function SetupSubmitFormDisabler() {
-  $('body').on('submit', 'form', function () {
-    $('body').focus();
-    $('form input,form select').prop('readonly', true);
+	$('body').on('submit', 'form', function () {
+		$('body').focus();
+		$('form input,form select').prop('readonly', true);
 
-    // Manual submit for more control
-    this.submit();
-    return false;
-  });
+		// Manual submit for more control
+		this.submit();
+		return false;
+	});
 }
 
 $(function () {
-  SetupConfirmationDialog();
+	SetupConfirmationDialog();
 
-  SetupSubmitFormDisabler();
+	SetupSubmitFormDisabler();
 });
 

+ 21 - 17
src/OpenMind/Admin/ui/masterpage.tpl

@@ -1,22 +1,22 @@
 <!DOCTYPE html>
 <html lang="it">
 <head>
-  <meta charset="UTF-8">
-  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
-  <title>{{@SITENAME}}</title>
-  <link type="text/css" rel="stylesheet" href="{{@BASEURL}}/{{@UI}}bundle.css"/>
-  <link rel="shortcut icon" type="image/x-icon" href="{{@BASEURL}}/{{@UI}}favicon.ico">
-
-  <script type="text/javascript">
-    const BASEURL = '{{@BASEURL}}';
-  </script>
+	<meta charset="UTF-8">
+	<meta content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no" name="viewport">
+	<title>{{@SITENAME}}</title>
+	<link href="{{@BASEURL}}/{{@UI}}bundle.css" rel="stylesheet" type="text/css"/>
+	<link href="{{@BASEURL}}/{{@UI}}favicon.ico" rel="shortcut icon" type="image/x-icon">
+
+	<script type="text/javascript">
+		const BASEURL = '{{@BASEURL}}';
+	</script>
 </head>
 <body>
 
 <include href="header.tpl"/>
 
 <div class="d-flex flex-row justify-content-around align-items-center" style="overflow-y: auto; height: calc(100% - 150px)">
-  <include if="{{isset(@CONTENT)}}" href="{{@CONTENT}}"/>
+	<include href="{{@CONTENT}}" if="{{isset(@CONTENT)}}"/>
 </div>
 
 <include href="footer.tpl"/>
@@ -24,13 +24,17 @@
 <script src="{{@BASEURL}}/{{@UI}}bundle.js"></script>
 
 <check if="{{isset(@REQ_REDIRECT}})">
-  <true>
-    <script>
-      setTimeout(() => {
-        window.location.href = "{{@BASEURL}}/{{@REQ_REDIRECT}}";
-      }, {{@REQ_REDIRECT_MS}});
-    </script>
-  </true>
+	<true>
+		<script>
+			setTimeout(() => {
+				window.location.href = "{{@BASEURL}}/{{@REQ_REDIRECT}}";
+			}, {;
+			{@REQ_REDIRECT_MS
+			}
+			})
+
+		</script>
+	</true>
 </check>
 
 </body>

+ 156 - 156
src/OpenMind/DataManager/CSVImporter.php

@@ -10,140 +10,112 @@ namespace OpenMind\DataManager;
 
 class ENUM_DIMATEC_CSV
 {
-  public const MXORDI = 7;
-  public const MXARTI = 10;
-  public const MXDESC = 12;
-  public const MXQTMI = 14;
-  public const MXUBIC = 16;
+	public const MXORDI = 7;
+	public const MXARTI = 10;
+	public const MXDESC = 12;
+	public const MXQTMI = 14;
+	public const MXUBIC = 16;
 }
 
 
 class CSVImporter
 {
-  const LAMBORGHINI_DISTINTA_COLONNE = 20;
-  const LAMBORGHINI_ARTICLES_COLONNE = 15;
-  const DIMATEC_LISTA_MOVIMENTI_AS400 = 32;
-
-  private $folderToWatch;
-  private $dbMysql;
-  private $output;
-  private $user;
-
-  /**
-   * @return mixed
-   */
-  public function getOutput()
-  {
-    return $this->output;
-  }
-
-  public function __construct(string $folderPath)
-  {
-    $this->user = (int)\F3::get('USER')->id;
-    $this->folderToWatch = $folderPath;
-    $this->dbMysql = \F3::get('DB');
-  }
-
-  /**
-   * Create MySQL temp table for smart operations
-   *
-   * @param string $table
-   * @return string temporary name
-   */
-  private function createTmpTableFrom(string $table)
-  {
-    $tempTableName = 'tmp' . rand(10, 200);
-    $this->dbMysql->exec("CREATE TEMPORARY TABLE IF NOT EXISTS `{$tempTableName}` AS (SELECT * FROM `{$table}`)");
-    return $tempTableName;
-  }
-
-  public function ScanAndStoreData()
-  {
-    foreach(glob("{$this->folderToWatch}/*.csv") as $fname) {
-      if (is_file($fname)) {
-        $allData = $this->loadCSV($fname);
-
-        // Esce se il file non è una distinta, lo riconosce solamente dal numero di colonne del file CSV
-        if ($allData == NULL)
-          return;
-
-        switch (count($allData[0])) {
-          case CSVImporter::LAMBORGHINI_DISTINTA_COLONNE:
-            $this->importOnDatabase($fname, $allData);
-            break;
-          case CSVImporter::LAMBORGHINI_ARTICLES_COLONNE:
-            $this->mysqlLoadCSV(addslashes(realpath($fname)), 'articles');
-            break;
-          case CSVImporter::DIMATEC_LISTA_MOVIMENTI_AS400:
-            //$tmpTableName = $this->createTmpTableFrom('distinte');
-            $this->dynamicImporter($fname, $allData, function ($data) {
-              if ($data[0] == "MXIDDM")
-                return;
-              try {
-                $distinta = new \DB\SQL\Mapper($this->dbMysql, 'distinte');
-                $distinta->idUtente = $this->user;
-                $distinta->commessa = $data[ENUM_DIMATEC_CSV::MXORDI];
-                $distinta->barcode = $data[ENUM_DIMATEC_CSV::MXARTI];
-                $distinta->descrizione = $data[ENUM_DIMATEC_CSV::MXDESC];
-                $distinta->qta_prelevare = $data[ENUM_DIMATEC_CSV::MXQTMI];
-                $distinta->save();
-              } catch (\PDOException $e) {
-                $this->output .= $e->getMessage();
-              }
-            });
-            /*            $this->dbMysql->exec(
-                          "INSERT INTO `distinta_esplosa` (commessa, barcode, descrizione, qta_prelevare) " .
-                          "SELECT commessa, barcode, descrizione, SUM(qta_prelevare) as qta_prelevare " .
-                          "FROM `distinte` group by barcode order by commessa"
-                        );*/
-            $this->markFileAsDone($fname);
-            break;
-          default:
-            $this->output .= "Numero di colonne non riconosciute ne come DISTINTA e ne come LISTA ARTICOLI per il file '{$fname}'";
-        }
-      }
-    }
-  }
-
-  private function loadCSV(string $path): ?array
-  {
-    $fh = fopen($path, "r");
-    $csvData = [];
-    while (($d = fgetcsv($fh, 0, ';'))) {
-      if ($d)
-        $csvData[] = $d;
-    }
-    fclose($fh);
-    return $csvData;
-  }
-
-  /**
-   * Iterate on $data and call $func to make operations on rows
-   *
-   * @param string $fileName
-   * @param array $data
-   * @param function(array $dataRow) $func
-   */
-  private function dynamicImporter(string $fileName, array $data, $func)
-  {
-    foreach($data as $dataRow) {
-      $func($dataRow);
-    }
-    $this->output .= "{$fileName} successfully imported<br/>";
-  }
-
-  /**
-   * @deprecated from 24/07/2018
-   * @param string $fileName
-   * @param array $data
-   */
-  private function importOnDatabase(string $fileName, array $data)
-  {
-    global $f3;
-    $this->dbMysql->query("TRUNCATE TABLE `distinte`");
-    foreach($data as $dataRow) {
-      $descr = addslashes($dataRow[10]);
-      $sql = <<<EOL
+	const LAMBORGHINI_DISTINTA_COLONNE = 20;
+	const LAMBORGHINI_ARTICLES_COLONNE = 15;
+	const DIMATEC_LISTA_MOVIMENTI_AS400 = 32;
+
+	private $folderToWatch;
+	private $dbMysql;
+	private $output;
+	private $user;
+
+	public function __construct(string $folderPath)
+	{
+		$this->user = (int)\F3::get('USER')->id;
+		$this->folderToWatch = $folderPath;
+		$this->dbMysql = \F3::get('DB');
+	}
+
+	/**
+	 * @return mixed
+	 */
+	public function getOutput()
+	{
+		return $this->output;
+	}
+
+	public function ScanAndStoreData()
+	{
+		foreach(glob("{$this->folderToWatch}/*.csv") as $fname) {
+			if (is_file($fname)) {
+				$allData = $this->loadCSV($fname);
+
+				// Esce se il file non è una distinta, lo riconosce solamente dal numero di colonne del file CSV
+				if ($allData == NULL)
+					return;
+
+				switch (count($allData[0])) {
+					case CSVImporter::LAMBORGHINI_DISTINTA_COLONNE:
+						$this->importOnDatabase($fname, $allData);
+						break;
+					case CSVImporter::LAMBORGHINI_ARTICLES_COLONNE:
+						$this->mysqlLoadCSV(addslashes(realpath($fname)), 'articles');
+						break;
+					case CSVImporter::DIMATEC_LISTA_MOVIMENTI_AS400:
+						//$tmpTableName = $this->createTmpTableFrom('distinte');
+						$this->dynamicImporter($fname, $allData, function ($data) {
+							if ($data[0] == "MXIDDM")
+								return;
+							try {
+								$distinta = new \DB\SQL\Mapper($this->dbMysql, 'distinte');
+								$distinta->idUtente = $this->user;
+								$distinta->commessa = $data[ENUM_DIMATEC_CSV::MXORDI];
+								$distinta->barcode = $data[ENUM_DIMATEC_CSV::MXARTI];
+								$distinta->descrizione = $data[ENUM_DIMATEC_CSV::MXDESC];
+								$distinta->qta_prelevare = $data[ENUM_DIMATEC_CSV::MXQTMI];
+								$distinta->save();
+							} catch (\PDOException $e) {
+								$this->output .= $e->getMessage();
+							}
+						});
+						/*            $this->dbMysql->exec(
+													"INSERT INTO `distinta_esplosa` (commessa, barcode, descrizione, qta_prelevare) " .
+													"SELECT commessa, barcode, descrizione, SUM(qta_prelevare) as qta_prelevare " .
+													"FROM `distinte` group by barcode order by commessa"
+												);*/
+						$this->markFileAsDone($fname);
+						break;
+					default:
+						$this->output .= "Numero di colonne non riconosciute ne come DISTINTA e ne come LISTA ARTICOLI per il file '{$fname}'";
+				}
+			}
+		}
+	}
+
+	private function loadCSV(string $path): ?array
+	{
+		$fh = fopen($path, "r");
+		$csvData = [];
+		while (($d = fgetcsv($fh, 0, ';'))) {
+			if ($d)
+				$csvData[] = $d;
+		}
+		fclose($fh);
+		return $csvData;
+	}
+
+	/**
+	 * @deprecated from 24/07/2018
+	 * @param string $fileName
+	 * @param array $data
+	 */
+	private function importOnDatabase(string $fileName, array $data)
+	{
+		global $f3;
+		$this->dbMysql->query("TRUNCATE TABLE `distinte`");
+		foreach($data as $dataRow) {
+			$descr = addslashes($dataRow[10]);
+			$sql = <<<EOL
 INSERT INTO distinte (
 origine, consegna, commessa, ordine_produzione, data_creazione, time_creazione, destinazione_merci, barcode, descrizione, qta_prelevare, qta_mancante
 ) VALUES (
@@ -151,34 +123,62 @@ origine, consegna, commessa, ordine_produzione, data_creazione, time_creazione,
 '$descr', '$dataRow[11]', 0
 );
 EOL;
-      if (!$this->dbMysql->query($sql)) {
-        echo "Error on query: {$sql}" . PHP_EOL;
-        echo $this->dbMysql->error . PHP_EOL;
-        return;
-      }
-    }
-    echo "{$fileName} successfully imported" . PHP_EOL;
-    $this->markFileAsDone($fileName);
-  }
-
-  private function markFileAsDone(string $csvPath)
-  {
-    rename($csvPath, "{$csvPath}_imported");
-  }
-
-  private function mysqlLoadCSV(string $CSVPath, string $tableName)
-  {
-    $this->dbMysql->query("TRUNCATE TABLE `{$tableName}`");
-    $sql = <<<EOF
+			if (!$this->dbMysql->query($sql)) {
+				echo "Error on query: {$sql}" . PHP_EOL;
+				echo $this->dbMysql->error . PHP_EOL;
+				return;
+			}
+		}
+		echo "{$fileName} successfully imported" . PHP_EOL;
+		$this->markFileAsDone($fileName);
+	}
+
+	private function markFileAsDone(string $csvPath)
+	{
+		rename($csvPath, "{$csvPath}_imported");
+	}
+
+	private function mysqlLoadCSV(string $CSVPath, string $tableName)
+	{
+		$this->dbMysql->query("TRUNCATE TABLE `{$tableName}`");
+		$sql = <<<EOF
 LOAD DATA INFILE '$CSVPath' INTO TABLE `$tableName`
 FIELDS TERMINATED BY ';' ENCLOSED BY '' LINES TERMINATED BY '\\n';
 EOF;
-    if (!$this->dbMysql->query($sql)) {
-      echo "Error on query: {$sql}" . PHP_EOL;
-      echo $this->dbMysql->error . PHP_EOL;
-      return;
-    }
-    echo "{$CSVPath} successfully imported" . PHP_EOL;
-    $this->markFileAsDone($CSVPath);
-  }
+		if (!$this->dbMysql->query($sql)) {
+			echo "Error on query: {$sql}" . PHP_EOL;
+			echo $this->dbMysql->error . PHP_EOL;
+			return;
+		}
+		echo "{$CSVPath} successfully imported" . PHP_EOL;
+		$this->markFileAsDone($CSVPath);
+	}
+
+	/**
+	 * Iterate on $data and call $func to make operations on rows
+	 *
+	 * @param string $fileName
+	 * @param array $data
+	 * @param function(array $dataRow) $func
+	 */
+	private function dynamicImporter(string $fileName, array $data, $func)
+	{
+		foreach($data as $dataRow) {
+			$func($dataRow);
+		}
+		$this->output .= "{$fileName} successfully imported<br/>";
+	}
+
+	/**
+	 * Create MySQL temp table for smart operations
+	 *
+	 * @param string $table
+	 * @return string temporary name
+	 */
+	private function createTmpTableFrom(string $table)
+	{
+		$tempTableName = 'tmp' . rand(10, 200);
+		$this->dbMysql->exec("CREATE TEMPORARY TABLE IF NOT EXISTS `{$tempTableName}` AS (SELECT * FROM `{$table}`)");
+		return $tempTableName;
+	}
 }

+ 5 - 5
src/OpenMind/FindBox/FindBox.php

@@ -12,11 +12,11 @@ use OpenMind\System\PluginStrategy;
 
 class FindBox extends PluginStrategy
 {
-  public function __construct()
-  {
-    // CLI scripts
-    $this->AddRoute('GET /cli.fb.service', __NAMESPACE__ . '\FindBoxService->Main');
-  }
+	public function __construct()
+	{
+		// CLI scripts
+		$this->AddRoute('GET /cli.fb.service', __NAMESPACE__ . '\FindBoxService->Main');
+	}
 }
 
 /** @var \OpenMind\FindBox\FindBox $FindBox */

+ 176 - 176
src/OpenMind/FindBox/FindBoxCoreSystem.php

@@ -14,184 +14,184 @@ use OpenMind\System\System;
 
 function array_filter_keys(array $array, array $keysToExtract)
 {
-  return array_intersect_key($array, array_flip($keysToExtract));
+	return array_intersect_key($array, array_flip($keysToExtract));
 }
 
 class FindBoxCoreSystem
 {
-  private $Host;
-  private $Port;
-  private $Key;
-  private $Pass;
-  private $coreDetails;
-
-  /**
-   * CoreLabel constructor.
-   *
-   * @param string $host hostname of FindBox OS system
-   * @param int $port
-   * @param string $APIKey
-   * @param string $Password
-   * @throws \Exception
-   */
-  public function __construct(string $host, int $port, string $APIKey, string $Password)
-  {
-    $this->Host = $host;
-    $this->Port = $port;
-    $this->Key = $APIKey;
-    $this->Pass = $Password;
-
-    Global $System;
-    /** @var System $System */
-    $Cache = $System->getCache();
-
-    if (!$Cache->exists('FindBoxCoreSystem')) {
-      $URI = '/1.0.0/index.php/getstatus/1.0.0/';
-      $ret = $this->CallAPI($URI, "");
-
-      if ($ret['err'] != 0)
-        throw new \Exception("Can't connect to FindBox server:<br/><br/>{$ret['value']}");
-
-      if ($ret['err'] == 0 && $ret['value']['code'] == 0) {
-        $details = $ret['value']['value'];
-        $this->coreDetails = array_filter_keys($details, ['core.box_id', 'core.version']);
-      }
-      $Cache->set('FindBoxCoreSystem', $this->coreDetails, 3600);
-    } else {
-      $this->coreDetails = $Cache->get('FindBoxCoreSystem');
-    }
-  }
-
-  /**
-   * CallGetAPI make HTTP GET requests
-   * @param string $URI full path of api url, for example "/1.0.0/index.php/smartesl.blink_special/1.0.0/"
-   * @param string $Parameters
-   * @param bool $skipResponse for faster communications, if response not need, you can skip this step
-   * @return array converted from JSON response of request if present
-   */
-  public function CallAPI(string $URI, string $Parameters, bool $skipResponse = false): array
-  {
-    $bodyJSON = null;
-    $auth = "Authorization: Basic " . base64_encode("{$this->Key}:{$this->Pass}") . "\r\n";
-
-    $streamfbOS = @stream_socket_client("tcp://{$this->Host}:{$this->Port}", $errno, $errstr, 1);
-    if (!$streamfbOS) {
-      return $this->returnCode($errno, $errstr);
-    } else {
-      //$requestText = "{$method} {$URI}{$Parameters} HTTP/1.0\r\nHost: {$this->Host}\r\n{$auth}Accept: */*\r\nConnection: close\r\n\r\n";
-      $requestBodyLength = strlen($Parameters);
-      $requestText = "POST {$URI} HTTP/1.0\r\nHost: {$this->Host}\r\n{$auth}Accept: */*\r\nContent-Type: application/json\r\nContent-Length: {$requestBodyLength}\r\n\r\n{$Parameters}\r\n";
-      //file_put_contents("request.txt", $requestText);
-      fwrite($streamfbOS, $requestText);
-      if (!$skipResponse) {
-        $r = stream_get_contents($streamfbOS);
-        list(, $bodyJSON) = explode("\r\n\r\n", $r, 2);
-      }
-      fclose($streamfbOS);
-    }
-
-    $bodyJSON = ($bodyJSON == null) ? "{}" : $bodyJSON;
-
-    return $this->returnCode(0, $bodyJSON);
-  }
-
-  /**
-   * Helper for make JSON return code
-   *
-   * @param int $errorCode
-   * @param string $value
-   * @return array
-   */
-  private function returnCode(int $errorCode, string $value): array
-  {
-    $val = json_decode($value, true) ?? $value;
-    return array(
-      "err" => $errorCode,
-      "value" => $val);
-  }
-
-  public function BlinkUnassigned()
-  {
-    $URI = "/1.0.0/index.php/smartesl.blink_unassigned/2.0.0/";
-    $this->CallAPI($URI, "", true);
-  }
-
-  /**
-   * Save products into findbus database
-   * @param string $barcode
-   * @param string $name
-   * @param array $dataFields Custom fields
-   * @return array
-   */
-  public function SaveProducts(string $barcode, string $name, array $dataFields): array
-  {
-    $product = json_encode([[[
-      "barcode" => $barcode,
-      "name1" => $name,
-      "datafields" => $dataFields
-    ]]]);
-
-    $URI = "/1.0.0/index.php/saveproducts/1.2.0/";
-
-    return $this->CallAPI($URI, $product);
-  }
-
-  /**
-   * Add label into findbox system and Bind it with a barcode
-   *
-   * @param string $labelId
-   * @param string $barcode
-   * @return array
-   */
-  public function Bind(string $labelId, string $barcode): array
-  {
-    $URI = "/1.0.0/index.php/smartesl.bind/1.1.0/";
-
-    return $this->CallAPI($URI, "[\"{$labelId}\",\"{$barcode}\"]");
-  }
-
-  /**
-   * Remove label from findbox system
-   *
-   * @param string $labelId
-   * @return array
-   */
-  public function UnBind(string $labelId): array
-  {
-    // Retrieve barcode associated to the label
-    $labelDetails = $this->CallAPI("/1.0.0/index.php/smartesl.getstatus/3.1.0/", "[[\"{$labelId}\"]]");
-    // If RSSI exist, label it is binded to system
-    if (isset($labelDetails['value']['value'][$labelId]['rssi'])) {
-      $barcode = $labelDetails['value']['value'][$labelId]['data']['barcode'];
-
-      $ret = $this->CallAPI("/1.0.0/index.php/smartesl.unbind/1.0.0/", "[\"{$labelId}\"]");
-      if ($ret['err'] != 0)
-        return $this->returnCode(1, 'Error on unbind');
-
-      $ret = $this->CallAPI("/1.0.0/index.php/deleteproducts/1.0.0/", "[\"{$barcode}\"]");
-      if ($ret['err'] != 0)
-        return $this->returnCode(1, 'Error on deleteproducts');
-
-      // All ok
-      return $this->returnCode(0, '');
-    } else
-      return $this->returnCode(1, 'No label exist on Findbox');
-  }
-
-  /**
-   * Check the response of FindBoxOS, return an array if no error, else NULL
-   *
-   * @param array $fbOS_Response
-   * @return NULL|array
-   */
-  public function getLabelsFromResponse(array $fbOS_Response): ?array
-  {
-    // Check if response have field 'value' that is an array
-    $haveArray = isset($fbOS_Response['value']['value']) && is_array($fbOS_Response['value']['value']);
-
-    if (!$haveArray)
-      return NULL;
-
-    return $fbOS_Response['value']['value'];
-  }
+	private $Host;
+	private $Port;
+	private $Key;
+	private $Pass;
+	private $coreDetails;
+
+	/**
+	 * CoreLabel constructor.
+	 *
+	 * @param string $host hostname of FindBox OS system
+	 * @param int $port
+	 * @param string $APIKey
+	 * @param string $Password
+	 * @throws \Exception
+	 */
+	public function __construct(string $host, int $port, string $APIKey, string $Password)
+	{
+		$this->Host = $host;
+		$this->Port = $port;
+		$this->Key = $APIKey;
+		$this->Pass = $Password;
+
+		Global $System;
+		/** @var System $System */
+		$Cache = $System->getCache();
+
+		if (!$Cache->exists('FindBoxCoreSystem')) {
+			$URI = '/1.0.0/index.php/getstatus/1.0.0/';
+			$ret = $this->CallAPI($URI, "");
+
+			if ($ret['err'] != 0)
+				throw new \Exception("Can't connect to FindBox server:<br/><br/>{$ret['value']}");
+
+			if ($ret['err'] == 0 && $ret['value']['code'] == 0) {
+				$details = $ret['value']['value'];
+				$this->coreDetails = array_filter_keys($details, ['core.box_id', 'core.version']);
+			}
+			$Cache->set('FindBoxCoreSystem', $this->coreDetails, 3600);
+		} else {
+			$this->coreDetails = $Cache->get('FindBoxCoreSystem');
+		}
+	}
+
+	/**
+	 * CallGetAPI make HTTP GET requests
+	 * @param string $URI full path of api url, for example "/1.0.0/index.php/smartesl.blink_special/1.0.0/"
+	 * @param string $Parameters
+	 * @param bool $skipResponse for faster communications, if response not need, you can skip this step
+	 * @return array converted from JSON response of request if present
+	 */
+	public function CallAPI(string $URI, string $Parameters, bool $skipResponse = false): array
+	{
+		$bodyJSON = null;
+		$auth = "Authorization: Basic " . base64_encode("{$this->Key}:{$this->Pass}") . "\r\n";
+
+		$streamfbOS = @stream_socket_client("tcp://{$this->Host}:{$this->Port}", $errno, $errstr, 1);
+		if (!$streamfbOS) {
+			return $this->returnCode($errno, $errstr);
+		} else {
+			//$requestText = "{$method} {$URI}{$Parameters} HTTP/1.0\r\nHost: {$this->Host}\r\n{$auth}Accept: */*\r\nConnection: close\r\n\r\n";
+			$requestBodyLength = strlen($Parameters);
+			$requestText = "POST {$URI} HTTP/1.0\r\nHost: {$this->Host}\r\n{$auth}Accept: */*\r\nContent-Type: application/json\r\nContent-Length: {$requestBodyLength}\r\n\r\n{$Parameters}\r\n";
+			//file_put_contents("request.txt", $requestText);
+			fwrite($streamfbOS, $requestText);
+			if (!$skipResponse) {
+				$r = stream_get_contents($streamfbOS);
+				list(, $bodyJSON) = explode("\r\n\r\n", $r, 2);
+			}
+			fclose($streamfbOS);
+		}
+
+		$bodyJSON = ($bodyJSON == null) ? "{}" : $bodyJSON;
+
+		return $this->returnCode(0, $bodyJSON);
+	}
+
+	/**
+	 * Helper for make JSON return code
+	 *
+	 * @param int $errorCode
+	 * @param string $value
+	 * @return array
+	 */
+	private function returnCode(int $errorCode, string $value): array
+	{
+		$val = json_decode($value, true) ?? $value;
+		return array(
+			"err" => $errorCode,
+			"value" => $val);
+	}
+
+	public function BlinkUnassigned()
+	{
+		$URI = "/1.0.0/index.php/smartesl.blink_unassigned/2.0.0/";
+		$this->CallAPI($URI, "", true);
+	}
+
+	/**
+	 * Save products into findbus database
+	 * @param string $barcode
+	 * @param string $name
+	 * @param array $dataFields Custom fields
+	 * @return array
+	 */
+	public function SaveProducts(string $barcode, string $name, array $dataFields): array
+	{
+		$product = json_encode([[[
+			"barcode" => $barcode,
+			"name1" => $name,
+			"datafields" => $dataFields
+		]]]);
+
+		$URI = "/1.0.0/index.php/saveproducts/1.2.0/";
+
+		return $this->CallAPI($URI, $product);
+	}
+
+	/**
+	 * Add label into findbox system and Bind it with a barcode
+	 *
+	 * @param string $labelId
+	 * @param string $barcode
+	 * @return array
+	 */
+	public function Bind(string $labelId, string $barcode): array
+	{
+		$URI = "/1.0.0/index.php/smartesl.bind/1.1.0/";
+
+		return $this->CallAPI($URI, "[\"{$labelId}\",\"{$barcode}\"]");
+	}
+
+	/**
+	 * Remove label from findbox system
+	 *
+	 * @param string $labelId
+	 * @return array
+	 */
+	public function UnBind(string $labelId): array
+	{
+		// Retrieve barcode associated to the label
+		$labelDetails = $this->CallAPI("/1.0.0/index.php/smartesl.getstatus/3.1.0/", "[[\"{$labelId}\"]]");
+		// If RSSI exist, label it is binded to system
+		if (isset($labelDetails['value']['value'][$labelId]['rssi'])) {
+			$barcode = $labelDetails['value']['value'][$labelId]['data']['barcode'];
+
+			$ret = $this->CallAPI("/1.0.0/index.php/smartesl.unbind/1.0.0/", "[\"{$labelId}\"]");
+			if ($ret['err'] != 0)
+				return $this->returnCode(1, 'Error on unbind');
+
+			$ret = $this->CallAPI("/1.0.0/index.php/deleteproducts/1.0.0/", "[\"{$barcode}\"]");
+			if ($ret['err'] != 0)
+				return $this->returnCode(1, 'Error on deleteproducts');
+
+			// All ok
+			return $this->returnCode(0, '');
+		} else
+			return $this->returnCode(1, 'No label exist on Findbox');
+	}
+
+	/**
+	 * Check the response of FindBoxOS, return an array if no error, else NULL
+	 *
+	 * @param array $fbOS_Response
+	 * @return NULL|array
+	 */
+	public function getLabelsFromResponse(array $fbOS_Response): ?array
+	{
+		// Check if response have field 'value' that is an array
+		$haveArray = isset($fbOS_Response['value']['value']) && is_array($fbOS_Response['value']['value']);
+
+		if (!$haveArray)
+			return NULL;
+
+		return $fbOS_Response['value']['value'];
+	}
 }

+ 180 - 180
src/OpenMind/FindBox/FindBoxService.php

@@ -13,184 +13,184 @@ use OpenMind\System\QueueSystem;
 
 class FindBoxService
 {
-  /** @var SQL $dbHandle */
-  private $dbHandle;
-  private $findBoxCore = null;
-  private $labelToBlink;
-  private $ServiceLogger;
-
-  public function __construct()
-  {
-    global $f3;
-
-    $this->ServiceLogger = new \Log('ServiceLogger.log');
-
-    $this->dbHandle = $f3->get('DB');
-    while ($this->findBoxCore == null)
-      try {
-        $this->findBoxCore = new FindBoxCoreSystem(...array_values($f3->get('CORE.fb')));
-      } catch (\Exception $e) {
-        $this->ServiceLogger->write("Can't find FindBoxCore, retry in 1 second..", 'd/m/Y H:i:s');
-        sleep(1);
-      }
-    $this->labelToBlink = [];
-  }
-
-  private function updateServiceStatus()
-  {
-    $qs = new QueueSystem('FindBoxService_isAlive');
-    if ($qs->check()) {
-      $qs->reset();
-      $qs->command = time();
-      $qs->servicename = 'FindBoxService_isAlive';
-      $qs->save();
-    } else {
-      $qs->command = time();
-    }
-    $qs->update();
-  }
-
-  private function getCurrentQueue()
-  {
-    global $f3;
-    $table = new QueueSystem('FindBoxService');
-    while (!$table->check()) {
-
-      /** @var QueueCommand $qCommand */
-      $qCommand = $table->getCommandObject();
-      switch ($qCommand->operation) {
-        case Q_SAVEPRODUCT:
-          $this->saveProduct($qCommand);
-          break;
-        case Q_BLINK_ON:
-        case Q_BLINK_OFF:
-          $this->labelToBlink[$qCommand->id] = $qCommand;
-          $this->labelToBlink[$qCommand->id]->retryForFault = $f3->get('MAX_RETRY_FOR_FAULT');
-          break;
-        case Q_DISPLAY:
-          $this->ServiceLogger->write("Change display for label {$qCommand->id} requested", 'd/m/Y H:i:s');
-          $esl = new SmartESL($this->findBoxCore, [$qCommand->id]);
-          $esl->Display($qCommand->params['templateId'], $qCommand->params['barcode']);
-          break;
-      }
-
-      $table->erase();
-      $table->next();
-    }
-  }
-
-  /**
-   * @param $labelId
-   * @param $fbError
-   * @return bool true if no error, false if error
-   */
-  private function ManageBlinkFaults($labelId, $fbError): bool
-  {
-    global $f3;
-    $labelResponses = $this->findBoxCore->getLabelsFromResponse($fbError);
-    $label = &$this->labelToBlink[$labelId];
-
-    if ($labelResponses && isset($labelResponses[$label->id]) && $labelResponses[$label->id]) { // Label exists and is true, mean that's all OK, no error
-      $label->retryForFault = $f3->get('MAX_RETRY_FOR_FAULT');
-      $label->tsLastLongBlink = time() + 2;
-      return true;
-    }
-
-    // Ho finito il numero di tentativi massimi?
-    if ($label->retryForFault < 0) {  // Rimuovo dalla coda l'etichetta
-      $this->ServiceLogger->write("Label {$label->id} fatal error. Removing from queue", 'd/m/Y H:i:s');
-      unset($this->labelToBlink[$labelId]);
-    } else {                          // Riprovo al prossimo ciclo
-      $this->ServiceLogger->write("Label {$label->id} blink error. Try next cycle...", 'd/m/Y H:i:s');
-      $label->tsLastLongBlink = 0;
-      $label->retryForFault--;
-    }
-
-    return false; // Default return value
-  }
-
-  /**
-   * Send SaveProduct to Label
-   *
-   * @param $label
-   * @return bool
-   */
-  public function saveProduct($label)
-  {
-    if ($label->operation == Q_SAVEPRODUCT) {
-      $this->findBoxCore->SaveProducts($label->id, $label->description, $label->params['dataFields']);
-      $this->ServiceLogger->write("Save product {$label->id}", 'd/m/Y H:i:s');
-      return true;
-    }
-    return false;
-  }
-
-  /**
-   * Called from php spawn process. This script end after MAX_BLINK_TIME
-   *
-   * @param \F3 $f3
-   */
-  public function Main($f3)
-  {
-    $this->ServiceLogger->write("Starting FindBoxService main loop", 'd/m/Y H:i:s');
-
-    while (true) {
-
-      $this->updateServiceStatus();
-
-      $this->getCurrentQueue();
-
-      foreach($this->labelToBlink as $labelId => &$label) {
-        switch ($label->operation) {
-
-          case Q_BLINK_OFF:
-            $this->ServiceLogger->write("BlinkOff for label {$label->id} requested", 'd/m/Y H:i:s');
-
-            $esl = new SmartESL($this->findBoxCore, [$label->id]);
-            $err = $esl->BlinkOff();
-
-            if ($this->ManageBlinkFaults($label->id, $err))
-              unset($this->labelToBlink[$labelId]);
-
-            break;
-
-          case Q_BLINK_ON:
-            // Priority 1
-            // ----------
-            // Force exit and blink off if run time script > MAX_BLINK_TIME_SEC
-            $now = time() - $label->tsFirstBlink;
-            if ($now > $f3->get('MAX_BLINK_TIME_SEC')) {
-              $this->ServiceLogger->write("Stop label {$label->id} for timeout", 'd/m/Y H:i:s');
-              $esl = new SmartESL($this->findBoxCore, [$label->id]);
-              $esl->BlinkOff();
-              unset($this->labelToBlink[$labelId]);
-              continue;
-            }
-
-            // Priority 2
-            // ----------
-            // Restart blink if blink is ended
-            $blinkEndTime = time() - $label->tsLastLongBlink;
-            /** @var QueueCommand $label */
-            $calcDuration = $label->getBlinkDuration();
-            if ($blinkEndTime > $calcDuration) {
-              $this->ServiceLogger->write("Auto restart blinking for label $label->id\n", 'd/m/Y H:i:s');
-
-              $esl = new SmartESL($this->findBoxCore, [$label->id]);
-              $ledParams = $label->params;
-
-              $err = $esl->BlinkSpecial($ledParams['pattern'], $ledParams['repeat'], $ledParams['iter_time'], $ledParams['iterations'], $ledParams['color']);
-
-              $this->ManageBlinkFaults($label->id, $err);
-
-            }
-            break;
-        }
-      }
-
-      usleep($f3->get('FINDBOXSERVICE.SLEEPTIME') * 1000);
-    }
-
-    return;
-  }
+	/** @var SQL $dbHandle */
+	private $dbHandle;
+	private $findBoxCore = null;
+	private $labelToBlink;
+	private $ServiceLogger;
+
+	public function __construct()
+	{
+		global $f3;
+
+		$this->ServiceLogger = new \Log('ServiceLogger.log');
+
+		$this->dbHandle = $f3->get('DB');
+		while ($this->findBoxCore == null)
+			try {
+				$this->findBoxCore = new FindBoxCoreSystem(...array_values($f3->get('CORE.fb')));
+			} catch (\Exception $e) {
+				$this->ServiceLogger->write("Can't find FindBoxCore, retry in 1 second..", 'd/m/Y H:i:s');
+				sleep(1);
+			}
+		$this->labelToBlink = [];
+	}
+
+	/**
+	 * Called from php spawn process. This script end after MAX_BLINK_TIME
+	 *
+	 * @param \F3 $f3
+	 */
+	public function Main($f3)
+	{
+		$this->ServiceLogger->write("Starting FindBoxService main loop", 'd/m/Y H:i:s');
+
+		while (true) {
+
+			$this->updateServiceStatus();
+
+			$this->getCurrentQueue();
+
+			foreach($this->labelToBlink as $labelId => &$label) {
+				switch ($label->operation) {
+
+					case Q_BLINK_OFF:
+						$this->ServiceLogger->write("BlinkOff for label {$label->id} requested", 'd/m/Y H:i:s');
+
+						$esl = new SmartESL($this->findBoxCore, [$label->id]);
+						$err = $esl->BlinkOff();
+
+						if ($this->ManageBlinkFaults($label->id, $err))
+							unset($this->labelToBlink[$labelId]);
+
+						break;
+
+					case Q_BLINK_ON:
+						// Priority 1
+						// ----------
+						// Force exit and blink off if run time script > MAX_BLINK_TIME_SEC
+						$now = time() - $label->tsFirstBlink;
+						if ($now > $f3->get('MAX_BLINK_TIME_SEC')) {
+							$this->ServiceLogger->write("Stop label {$label->id} for timeout", 'd/m/Y H:i:s');
+							$esl = new SmartESL($this->findBoxCore, [$label->id]);
+							$esl->BlinkOff();
+							unset($this->labelToBlink[$labelId]);
+							continue;
+						}
+
+						// Priority 2
+						// ----------
+						// Restart blink if blink is ended
+						$blinkEndTime = time() - $label->tsLastLongBlink;
+						/** @var QueueCommand $label */
+						$calcDuration = $label->getBlinkDuration();
+						if ($blinkEndTime > $calcDuration) {
+							$this->ServiceLogger->write("Auto restart blinking for label $label->id\n", 'd/m/Y H:i:s');
+
+							$esl = new SmartESL($this->findBoxCore, [$label->id]);
+							$ledParams = $label->params;
+
+							$err = $esl->BlinkSpecial($ledParams['pattern'], $ledParams['repeat'], $ledParams['iter_time'], $ledParams['iterations'], $ledParams['color']);
+
+							$this->ManageBlinkFaults($label->id, $err);
+
+						}
+						break;
+				}
+			}
+
+			usleep($f3->get('FINDBOXSERVICE.SLEEPTIME') * 1000);
+		}
+
+		return;
+	}
+
+	private function updateServiceStatus()
+	{
+		$qs = new QueueSystem('FindBoxService_isAlive');
+		if ($qs->check()) {
+			$qs->reset();
+			$qs->command = time();
+			$qs->servicename = 'FindBoxService_isAlive';
+			$qs->save();
+		} else {
+			$qs->command = time();
+		}
+		$qs->update();
+	}
+
+	private function getCurrentQueue()
+	{
+		global $f3;
+		$table = new QueueSystem('FindBoxService');
+		while (!$table->check()) {
+
+			/** @var QueueCommand $qCommand */
+			$qCommand = $table->getCommandObject();
+			switch ($qCommand->operation) {
+				case Q_SAVEPRODUCT:
+					$this->saveProduct($qCommand);
+					break;
+				case Q_BLINK_ON:
+				case Q_BLINK_OFF:
+					$this->labelToBlink[$qCommand->id] = $qCommand;
+					$this->labelToBlink[$qCommand->id]->retryForFault = $f3->get('MAX_RETRY_FOR_FAULT');
+					break;
+				case Q_DISPLAY:
+					$this->ServiceLogger->write("Change display for label {$qCommand->id} requested", 'd/m/Y H:i:s');
+					$esl = new SmartESL($this->findBoxCore, [$qCommand->id]);
+					$esl->Display($qCommand->params['templateId'], $qCommand->params['barcode']);
+					break;
+			}
+
+			$table->erase();
+			$table->next();
+		}
+	}
+
+	/**
+	 * Send SaveProduct to Label
+	 *
+	 * @param $label
+	 * @return bool
+	 */
+	public function saveProduct($label)
+	{
+		if ($label->operation == Q_SAVEPRODUCT) {
+			$this->findBoxCore->SaveProducts($label->id, $label->description, $label->params['dataFields']);
+			$this->ServiceLogger->write("Save product {$label->id}", 'd/m/Y H:i:s');
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * @param $labelId
+	 * @param $fbError
+	 * @return bool true if no error, false if error
+	 */
+	private function ManageBlinkFaults($labelId, $fbError): bool
+	{
+		global $f3;
+		$labelResponses = $this->findBoxCore->getLabelsFromResponse($fbError);
+		$label = &$this->labelToBlink[$labelId];
+
+		if ($labelResponses && isset($labelResponses[$label->id]) && $labelResponses[$label->id]) { // Label exists and is true, mean that's all OK, no error
+			$label->retryForFault = $f3->get('MAX_RETRY_FOR_FAULT');
+			$label->tsLastLongBlink = time() + 2;
+			return true;
+		}
+
+		// Ho finito il numero di tentativi massimi?
+		if ($label->retryForFault < 0) {  // Rimuovo dalla coda l'etichetta
+			$this->ServiceLogger->write("Label {$label->id} fatal error. Removing from queue", 'd/m/Y H:i:s');
+			unset($this->labelToBlink[$labelId]);
+		} else {                          // Riprovo al prossimo ciclo
+			$this->ServiceLogger->write("Label {$label->id} blink error. Try next cycle...", 'd/m/Y H:i:s');
+			$label->tsLastLongBlink = 0;
+			$label->retryForFault--;
+		}
+
+		return false; // Default return value
+	}
 }

+ 77 - 77
src/OpenMind/FindBox/QueueCommand.php

@@ -15,89 +15,89 @@ define('Q_DISPLAY', 4);
 
 class QueueCommand
 {
-  public $id;
-  public $operation;
-  public $description;
-  public $params;
-  public $tsFirstBlink;
-  public $tsLastLongBlink;
+	public $id;
+	public $operation;
+	public $description;
+	public $params;
+	public $tsFirstBlink;
+	public $tsLastLongBlink;
 
-  public function __construct(string $labelID)
-  {
-    $this->id = $labelID;
-    $this->params = null;
-    $this->tsLastLongBlink = time() - 3600;
-    $this->tsFirstBlink = time();
-  }
+	public function __construct(string $labelID)
+	{
+		$this->id = $labelID;
+		$this->params = null;
+		$this->tsLastLongBlink = time() - 3600;
+		$this->tsFirstBlink = time();
+	}
 
-  /**
-   * Add custom property
-   *
-   * @param $name
-   * @param $value
-   */
-  public function __set($name, $value)
-  {
-    $this->{$name} = $value;
-  }
+	/**
+	 * Get custom property
+	 *
+	 * @param $name
+	 * @return mixed
+	 */
+	public function __get($name)
+	{
+		return $this->{$name};
+	}
 
-  /**
-   * Get custom property
-   *
-   * @param $name
-   * @return mixed
-   */
-  public function __get($name)
-  {
-    return $this->{$name};
-  }
+	/**
+	 * Add custom property
+	 *
+	 * @param $name
+	 * @param $value
+	 */
+	public function __set($name, $value)
+	{
+		$this->{$name} = $value;
+	}
 
-  public function setLeds(int $pattern, int $repeat, int $iter_time, int $iterations, int $color)
-  {
-    $this->operation = Q_BLINK_ON;
-    list(
-      $this->params['pattern'],
-      $this->params['repeat'],
-      $this->params['iter_time'],
-      $this->params['iterations'],
-      $this->params['color']
-      ) = func_get_args();
-  }
+	public function setLeds(int $pattern, int $repeat, int $iter_time, int $iterations, int $color)
+	{
+		$this->operation = Q_BLINK_ON;
+		list(
+			$this->params['pattern'],
+			$this->params['repeat'],
+			$this->params['iter_time'],
+			$this->params['iterations'],
+			$this->params['color']
+			) = func_get_args();
+	}
 
-  public function saveProducts(string $description, array $dataFields)
-  {
-    $this->operation = Q_SAVEPRODUCT;
-    $this->description = $description;
-    $this->params['dataFields'] = $dataFields;
-  }
+	public function saveProducts(string $description, array $dataFields)
+	{
+		$this->operation = Q_SAVEPRODUCT;
+		$this->description = $description;
+		$this->params['dataFields'] = $dataFields;
+	}
 
-  public function setToBlinkOff()
-  {
-    $this->operation = Q_BLINK_OFF;
-  }
+	public function setToBlinkOff()
+	{
+		$this->operation = Q_BLINK_OFF;
+	}
 
-  /**
-   * Calculate blink duration in seconds for patterns_type=2
-   *
-   * @return int
-   */
-  public function getBlinkDuration(): int
-  {
-    return (($this->params['iter_time'] / 1000) * ($this->params['iterations'] - 1)) * $this->params['repeat'];
-  }
+	/**
+	 * Calculate blink duration in seconds for patterns_type=2
+	 *
+	 * @return int
+	 */
+	public function getBlinkDuration(): int
+	{
+		return (($this->params['iter_time'] / 1000) * ($this->params['iterations'] - 1)) * $this->params['repeat'];
+	}
 
-  /**
-   * Set Display ID
-   *
-   * @param string $templateId
-   * @param string $barcode
-   */
-  public function setDisplay(string $templateId, string $barcode)
-  {
-    $this->operation = Q_DISPLAY;
-    list(
-      $this->params['templateId'],
-      $this->params['barcode']
-      ) = func_get_args();
-  }
+	/**
+	 * Set Display ID
+	 *
+	 * @param string $templateId
+	 * @param string $barcode
+	 */
+	public function setDisplay(string $templateId, string $barcode)
+	{
+		$this->operation = Q_DISPLAY;
+		list(
+			$this->params['templateId'],
+			$this->params['barcode']
+			) = func_get_args();
+	}
 }

+ 131 - 131
src/OpenMind/FindBox/SmartESL.php

@@ -9,135 +9,135 @@ namespace OpenMind\FindBox;
 
 class SmartESL
 {
-  private $core;
-  private $labels;
-  private $labelProperties;
-
-  public function __construct(FindBoxCoreSystem $coreL, array $LabelID)
-  {
-    $this->core = $coreL;
-    $this->labels = array_map('strtoupper', $LabelID);
-    // TODO utilizzare la $Cache di F3 per velocizzare le operazioni
-    $this->labelProperties = $this->GetStatus();
-  }
-
-  /**
-   * Request to label(s) its properties
-   * @return null|object Details
-   */
-  public function GetStatus()
-  {
-    $labels = json_encode(array($this->labels));
-    $URI = "/1.0.0/index.php/smartesl.getstatus/3.1.0/";
-    $ret = $this->core->CallAPI($URI, $labels);
-    if ($ret['err'] == 0 && $ret['value']['code'] == 0) {
-      // Update current properties
-      $this->labelProperties = $ret['value']['value'];
-      return $this->labelProperties;
-    }
-    return null;
-  }
-
-  /**
-   * Retrieve cached label properties
-   *
-   * @return null|object
-   */
-  public function getDetails()
-  {
-    return $this->labelProperties;
-  }
-
-  /**
-   * Get label version splitted into the three components major, minor, patch
-   *
-   * @return array
-   */
-  public function GetVersion()
-  {
-    $softVersion = $this->labelProperties[array_keys($this->labelProperties)[0]]['status'];
-    return array_values(array_filter_keys($softVersion, ['soft_major', 'soft_minor', 'soft_patch']));
-  }
-
-  public function getData()
-  {
-    return $this->labelProperties[$this->labels[0]]['data'];
-  }
-
-  /**
-   * Blink the label with parameters. BlinkSpecial make use of getData() and check how many leds has to auto select the firmware version.
-   *
-   * @param int $pattern
-   * @param int $repeat
-   * @param int $iter_time
-   * @param int $iterations
-   * @param int|null $ledColor
-   * @return array
-   */
-  public function BlinkSpecial(int $pattern, int $repeat, int $iter_time, int $iterations, int $ledColor = null)
-  {
-    $numLeds = $this->getData()['led'];
-    switch ($numLeds) {
-      case 2:
-        $version = 4;
-        break;
-      case 4:
-        $version = 6;
-        break;
-      default:
-        $version = 3;
-        break;
-    }
-    $firmwareStringVersion = array(
-      '3' => '1.0.0',
-      '4' => '1.1.0',
-      '6' => '2.0.0'
-    );
-
-    $params = array(
-      '3' => array($pattern, $repeat, $iter_time, $iterations, 1),
-      '4' => array($pattern, $repeat, $iter_time, $iterations, 1),
-      '6' => array($pattern, $ledColor, $repeat, $iter_time, $iterations, 1)
-
-    );
-
-    // TODO #NODISPLAY da sistemare
-    $strFWVer = $firmwareStringVersion[$version];
-
-    $uriParams = json_encode(array_merge(
-      array($this->labels),
-      $params[$version]));
-
-    $URI = "/1.0.0/index.php/smartesl.blink_special/{$strFWVer}/";
-    return $this->core->CallAPI($URI, $uriParams);
-  }
-
-  /**
-   * Turn off led(s)
-   */
-  public function BlinkOff()
-  {
-    $URI = "/1.0.0/index.php/smartesl.blink_special/2.0.0/";
-    return $this->core->CallAPI($URI, "[[\"{$this->labels[0]}\"],0,0,0,0,0,1]");
-  }
-
-  public function Display(string $templateId, string $barcode)
-  {
-    $URI = "/1.0.0/index.php/smartesl.display/2.3.0/";
-    $params = json_encode(array(
-      $this->labels[0],
-      $barcode,
-      [],
-      $templateId,
-      1, 1));
-
-    return $this->core->CallAPI($URI, $params);
-
-  }
-
-  public function GetLabelMatch()
-  {
-    $URI = "/1.0.0/index.php/smartesl.getlabelmatch/1.2.0/";
-    return $this->core->CallAPI($URI, json_encode(array($this->labels)));
-  }
+	private $core;
+	private $labels;
+	private $labelProperties;
+
+	public function __construct(FindBoxCoreSystem $coreL, array $LabelID)
+	{
+		$this->core = $coreL;
+		$this->labels = array_map('strtoupper', $LabelID);
+		// TODO utilizzare la $Cache di F3 per velocizzare le operazioni
+		$this->labelProperties = $this->GetStatus();
+	}
+
+	/**
+	 * Request to label(s) its properties
+	 * @return null|object Details
+	 */
+	public function GetStatus()
+	{
+		$labels = json_encode(array($this->labels));
+		$URI = "/1.0.0/index.php/smartesl.getstatus/3.1.0/";
+		$ret = $this->core->CallAPI($URI, $labels);
+		if ($ret['err'] == 0 && $ret['value']['code'] == 0) {
+			// Update current properties
+			$this->labelProperties = $ret['value']['value'];
+			return $this->labelProperties;
+		}
+		return null;
+	}
+
+	/**
+	 * Retrieve cached label properties
+	 *
+	 * @return null|object
+	 */
+	public function getDetails()
+	{
+		return $this->labelProperties;
+	}
+
+	/**
+	 * Get label version splitted into the three components major, minor, patch
+	 *
+	 * @return array
+	 */
+	public function GetVersion()
+	{
+		$softVersion = $this->labelProperties[array_keys($this->labelProperties)[0]]['status'];
+		return array_values(array_filter_keys($softVersion, ['soft_major', 'soft_minor', 'soft_patch']));
+	}
+
+	/**
+	 * Blink the label with parameters. BlinkSpecial make use of getData() and check how many leds has to auto select the firmware version.
+	 *
+	 * @param int $pattern
+	 * @param int $repeat
+	 * @param int $iter_time
+	 * @param int $iterations
+	 * @param int|null $ledColor
+	 * @return array
+	 */
+	public function BlinkSpecial(int $pattern, int $repeat, int $iter_time, int $iterations, int $ledColor = null)
+	{
+		$numLeds = $this->getData()['led'];
+		switch ($numLeds) {
+			case 2:
+				$version = 4;
+				break;
+			case 4:
+				$version = 6;
+				break;
+			default:
+				$version = 3;
+				break;
+		}
+		$firmwareStringVersion = array(
+			'3' => '1.0.0',
+			'4' => '1.1.0',
+			'6' => '2.0.0'
+		);
+
+		$params = array(
+			'3' => array($pattern, $repeat, $iter_time, $iterations, 1),
+			'4' => array($pattern, $repeat, $iter_time, $iterations, 1),
+			'6' => array($pattern, $ledColor, $repeat, $iter_time, $iterations, 1)
+
+		);
+
+		// TODO #NODISPLAY da sistemare
+		$strFWVer = $firmwareStringVersion[$version];
+
+		$uriParams = json_encode(array_merge(
+			array($this->labels),
+			$params[$version]));
+
+		$URI = "/1.0.0/index.php/smartesl.blink_special/{$strFWVer}/";
+		return $this->core->CallAPI($URI, $uriParams);
+	}
+
+	public function getData()
+	{
+		return $this->labelProperties[$this->labels[0]]['data'];
+	}
+
+	/**
+	 * Turn off led(s)
+	 */
+	public function BlinkOff()
+	{
+		$URI = "/1.0.0/index.php/smartesl.blink_special/2.0.0/";
+		return $this->core->CallAPI($URI, "[[\"{$this->labels[0]}\"],0,0,0,0,0,1]");
+	}
+
+	public function Display(string $templateId, string $barcode)
+	{
+		$URI = "/1.0.0/index.php/smartesl.display/2.3.0/";
+		$params = json_encode(array(
+			$this->labels[0],
+			$barcode,
+			[],
+			$templateId,
+			1, 1));
+
+		return $this->core->CallAPI($URI, $params);
+
+	}
+
+	public function GetLabelMatch()
+	{
+		$URI = "/1.0.0/index.php/smartesl.getlabelmatch/1.2.0/";
+		return $this->core->CallAPI($URI, json_encode(array($this->labels)));
+	}
 }

+ 59 - 59
src/OpenMind/System/ErrorHandlers.php

@@ -10,64 +10,64 @@ namespace OpenMind\System;
 
 class ErrorHandlers
 {
-  private $f3;
-
-  public function __construct()
-  {
-    $this->f3 = \Base::instance();
-  }
-
-  /**
-   * Main error handler: managed AJAX and non-AJAX calls
-   */
-  public function Handler()
-  {
-    $arrayError = array($this->f3->get('ERROR')['code'], $this->f3->get('ERROR')['status'], $this->f3->get('ERROR')['text']);
-
-    while (ob_get_level()) // Prevent to output all previous templates
-      ob_end_clean();
-
-    $err = $this->f3->get('ERROR');
-
-    $this->WriteLog(join(' - ', array($err['code'], $err['status'], $err['text'])));
-
-    if ($this->f3->get('CLI')) {
-      print_r($arrayError);
-      die(1);
-    }
-
-    if (!$this->f3->get('AJAX')) {
-      echo \Template::instance()->render('errors.tpl');
-      return;
-    }
-
-    // with return FALSE i leave to F3 the output of error code in AJAX
-    //http_response_code(400);
-    //echo join(' - ', $arrayError);
-    return FALSE;
-  }
-
-  /**
-   * Simple function to write to default log file
-   * @param string $logMessage
-   * @param int $traceNumber trace index of debug_backtrace() return array, default 1
-   */
-  private function WriteLog(string $logMessage, int $traceNumber = 1)
-  {
-    $trace = debug_backtrace();
-
-    if (count($trace) > 1) {
-      $trace = $trace[$traceNumber];
-
-      $method = isset($trace['function']) ? $trace['function'] . ':' : '';
-      $class = isset($trace['class']) ? $trace['class'] . ':' : '';
-      $line = isset($trace['line']) ? $trace['line'] . ':' : '';
-      //$userAgent = '(' . join(', ', $UA) . ')';
-      OMUtils::getInstance()->getLogger()->write("{$line}{$class}{$method} " . str_replace(array("\r", "\n"), '', $logMessage), 'd/m/Y H:i:s');
-      return;
-    }
-
-    OMUtils::getInstance()->getLogger()->write($logMessage, 'd/m/Y H:i:s');
-  }
+	private $f3;
+
+	public function __construct()
+	{
+		$this->f3 = \Base::instance();
+	}
+
+	/**
+	 * Main error handler: managed AJAX and non-AJAX calls
+	 */
+	public function Handler()
+	{
+		$arrayError = array($this->f3->get('ERROR')['code'], $this->f3->get('ERROR')['status'], $this->f3->get('ERROR')['text']);
+
+		while (ob_get_level()) // Prevent to output all previous templates
+			ob_end_clean();
+
+		$err = $this->f3->get('ERROR');
+
+		$this->WriteLog(join(' - ', array($err['code'], $err['status'], $err['text'])));
+
+		if ($this->f3->get('CLI')) {
+			print_r($arrayError);
+			die(1);
+		}
+
+		if (!$this->f3->get('AJAX')) {
+			echo \Template::instance()->render('errors.tpl');
+			return;
+		}
+
+		// with return FALSE i leave to F3 the output of error code in AJAX
+		//http_response_code(400);
+		//echo join(' - ', $arrayError);
+		return FALSE;
+	}
+
+	/**
+	 * Simple function to write to default log file
+	 * @param string $logMessage
+	 * @param int $traceNumber trace index of debug_backtrace() return array, default 1
+	 */
+	private function WriteLog(string $logMessage, int $traceNumber = 1)
+	{
+		$trace = debug_backtrace();
+
+		if (count($trace) > 1) {
+			$trace = $trace[$traceNumber];
+
+			$method = isset($trace['function']) ? $trace['function'] . ':' : '';
+			$class = isset($trace['class']) ? $trace['class'] . ':' : '';
+			$line = isset($trace['line']) ? $trace['line'] . ':' : '';
+			//$userAgent = '(' . join(', ', $UA) . ')';
+			OMUtils::getInstance()->getLogger()->write("{$line}{$class}{$method} " . str_replace(array("\r", "\n"), '', $logMessage), 'd/m/Y H:i:s');
+			return;
+		}
+
+		OMUtils::getInstance()->getLogger()->write($logMessage, 'd/m/Y H:i:s');
+	}
 
 }

+ 57 - 57
src/OpenMind/System/Notifications.php

@@ -12,68 +12,68 @@ use DB\SQL\Mapper;
 
 class Notifications extends Mapper
 {
-  const FB_GENERIC = 0x01;
-  const FB_IMPORT = 0x02;
-  const FB_NOTALIVE = 0x0B;
-  /**
-   * If you need custom notification or to simply send a command to client use FB_CUSTOM_NOTIFICATION+xxx where xxx is a number that identify your notification
-   */
-  const FB_CUSTOM_NOTIFICATION = 0x4000;
-  const FB_REFRESH_FILTERS = Notifications::FB_CUSTOM_NOTIFICATION + 1;
+	const FB_GENERIC = 0x01;
+	const FB_IMPORT = 0x02;
+	const FB_NOTALIVE = 0x0B;
+	/**
+	 * If you need custom notification or to simply send a command to client use FB_CUSTOM_NOTIFICATION+xxx where xxx is a number that identify your notification
+	 */
+	const FB_CUSTOM_NOTIFICATION = 0x4000;
+	const FB_REFRESH_FILTERS = Notifications::FB_CUSTOM_NOTIFICATION + 1;
 
-  public function __construct()
-  {
-    global $f3;
+	public function __construct()
+	{
+		global $f3;
 
-    parent::__construct($f3->get('DB'), 'notifications');
-  }
+		parent::__construct($f3->get('DB'), 'notifications');
+	}
 
-  /**
-   * @param int $code of notification to remove from database
-   */
-  public function Remove(int $code)
-  {
-    $this->reset();
-    $this->erase(['code=?', $code]);
-  }
+	/**
+	 * @param int $code of notification to remove from database
+	 */
+	public function Remove(int $code)
+	{
+		$this->reset();
+		$this->erase(['code=?', $code]);
+	}
 
-  /**
-   * Check if notification $code exists
-   *
-   * @param int $code
-   * @return bool
-   */
-  public function check(int $code)
-  {
-    $this->load(['code=?', $code]);
-    return $this->dry();
-  }
+	/**
+	 * Truncate all table
+	 */
+	public function emptyAll()
+	{
+		global $f3;
 
-  /**
-   * Truncate all table
-   */
-  public function emptyAll()
-  {
-    global $f3;
+		$f3->get('DB')->exec('TRUNCATE TABLE notifications');
+	}
 
-    $f3->get('DB')->exec('TRUNCATE TABLE notifications');
-  }
+	/**
+	 * Send custom notification to system
+	 *
+	 * @param int $code maybe FB_GENERIC, FB_IMPORT, etc
+	 * @param string|null $caption
+	 * @param null $link
+	 */
+	public function notify(int $code, string $caption = null, $link = null)
+	{
+		if ($code == $this::FB_GENERIC || $this->check($code)) {
+			$this->reset();
+			$this->code = $code;
+			$this->caption = $caption;
+			$this->link = $link;
+			$this->save();
+		}
+	}
 
-  /**
-   * Send custom notification to system
-   *
-   * @param int $code maybe FB_GENERIC, FB_IMPORT, etc
-   * @param string|null $caption
-   * @param null $link
-   */
-  public function notify(int $code, string $caption = null, $link = null)
-  {
-    if ($code == $this::FB_GENERIC || $this->check($code)) {
-      $this->reset();
-      $this->code = $code;
-      $this->caption = $caption;
-      $this->link = $link;
-      $this->save();
-    }
-  }
+	/**
+	 * Check if notification $code exists
+	 *
+	 * @param int $code
+	 * @return bool
+	 */
+	public function check(int $code)
+	{
+		$this->load(['code=?', $code]);
+		return $this->dry();
+	}
 }

+ 108 - 108
src/OpenMind/System/OMUtils.php

@@ -15,123 +15,123 @@ use RecursiveIteratorIterator;
 class OMUtils
 {
 
-  private $Logger;
+	private $Logger;
 
-  public function __construct()
-  {
-    $this->Logger = new \Log('Site.log');
-  }
+	public function __construct()
+	{
+		$this->Logger = new \Log('Site.log');
+	}
 
-  /**
-   * Get logger classe
-   *
-   * @return \Log
-   */
-  public function getLogger(): \Log
-  {
-    return $this->Logger;
-  }
+	/**
+	 * The Singleton Instance
+	 *
+	 * @return null|OMUtils
+	 */
+	public static function getInstance(): ?OMUtils
+	{
+		static $instance = null;
+		if ($instance === null) {
+			$instance = new static(); // PHP 5+ lazy state building
+		}
+		return $instance;
+	}
 
-  /**
-   * The Singleton Instance
-   *
-   * @return null|OMUtils
-   */
-  public static function getInstance(): ?OMUtils
-  {
-    static $instance = null;
-    if ($instance === null) {
-      $instance = new static(); // PHP 5+ lazy state building
-    }
-    return $instance;
-  }
+	/**
+	 * Get logger classe
+	 *
+	 * @return \Log
+	 */
+	public function getLogger(): \Log
+	{
+		return $this->Logger;
+	}
 
-  /**
-   * Load all modules in <$path> folder
-   * @param string $path
-   */
-  public function PluginLoader(string $path)
-  {
-    // <class priority>
-    //TODO if is necessary to give a priority to some classes before other, initialize here
-    Global $System, $Web;
-    $System = new System();  // we need System Base class first, so will force to load as first
-    $Web = new Web();
-    // </class priority>
-    $Directory = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
-    $Iterator = new RecursiveIteratorIterator($Directory, RecursiveIteratorIterator::CHILD_FIRST);
+	/**
+	 * Load all modules in <$path> folder
+	 * @param string $path
+	 */
+	public function PluginLoader(string $path)
+	{
+		// <class priority>
+		//TODO if is necessary to give a priority to some classes before other, initialize here
+		Global $System, $Web;
+		$System = new System();  // we need System Base class first, so will force to load as first
+		$Web = new Web();
+		// </class priority>
+		$Directory = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
+		$Iterator = new RecursiveIteratorIterator($Directory, RecursiveIteratorIterator::CHILD_FIRST);
 
-    foreach($Iterator as $item) {
-      if (is_file($item->getPathname()))
-        continue;
-      $moduleName = $item->getFilename();
-      $className = str_replace('/', '\\', ltrim("{$item->getPathname()}/{$moduleName}", $path));
-      // Load only PHP file with same name of namespace ex.: \Lamborghini\Lamborghini.php
-      $moduleInitPath = "{$item->getPathname()}/{$moduleName}.php";
-      if (file_exists($moduleInitPath)) { // If already imported, skip
-        if (!isset($$moduleName)) {
-          Global $$moduleName;  // Declare visibility to Global
-          $$moduleName = new $className(); // Instantiate the Module, all init procedure must reside in __constructor() method
-        }
-      }
-    }
-  }
+		foreach($Iterator as $item) {
+			if (is_file($item->getPathname()))
+				continue;
+			$moduleName = $item->getFilename();
+			$className = str_replace('/', '\\', ltrim("{$item->getPathname()}/{$moduleName}", $path));
+			// Load only PHP file with same name of namespace ex.: \Lamborghini\Lamborghini.php
+			$moduleInitPath = "{$item->getPathname()}/{$moduleName}.php";
+			if (file_exists($moduleInitPath)) { // If already imported, skip
+				if (!isset($$moduleName)) {
+					Global $$moduleName;  // Declare visibility to Global
+					$$moduleName = new $className(); // Instantiate the Module, all init procedure must reside in __constructor() method
+				}
+			}
+		}
+	}
 
-  /**
-   * Use F3 template resolve() to parse string like "{{@BASESITE}}"
-   *
-   * @param string $strTemplate the F3 original string
-   * @return string converted string
-   */
-  public function getStringFromTemplate(string $strTemplate)
-  {
-    return \Template::instance()->resolve($strTemplate);
-  }
+	/**
+	 * Use F3 template resolve() to parse string like "{{@BASESITE}}"
+	 *
+	 * @param string $strTemplate the F3 original string
+	 * @return string converted string
+	 */
+	public function getStringFromTemplate(string $strTemplate)
+	{
+		return \Template::instance()->resolve($strTemplate);
+	}
 
 
-  /**
-   * Load an encrypted file with the method "base64_encode(gzcompress(<path to config.ini>))", save it in a temporary file in temp folder of system and load with F3::config()
-   *
-   * @param string $path
-   * @throws \Exception
-   */
-  public function LoadEncryptedConfig(string $path)
-  {
-    global $f3;
-    if (!file_exists($path))
-      throw new \Exception('Config file not found');
+	/**
+	 * Load an encrypted file with the method "base64_encode(gzcompress(<path to config.ini>))", save it in a temporary file in temp folder of system and load with F3::config()
+	 *
+	 * @param string $path
+	 * @throws \Exception
+	 */
+	public function LoadEncryptedConfig(string $path)
+	{
+		global $f3;
+		if (!file_exists($path))
+			throw new \Exception('Config file not found');
 
-    $tmpFilepath = tempnam(sys_get_temp_dir(), 'om');
-    $config = gzuncompress(base64_decode(file_get_contents($path)));
-    file_put_contents($tmpFilepath, $config);
-    $f3->config($tmpFilepath, true);
-    unlink($tmpFilepath);
-  }
+		$tmpFilepath = tempnam(sys_get_temp_dir(), 'om');
+		$config = gzuncompress(base64_decode(file_get_contents($path)));
+		file_put_contents($tmpFilepath, $config);
+		$f3->config($tmpFilepath, true);
+		unlink($tmpFilepath);
+	}
 
-  /*
-   * Exit from APP if the OMLINK requirement aren't meet
-   */
-  public function DieByOldPhpVersion()
-  {
-    if (version_compare(PHP_VERSION, '7.2') != 1)
-      throw new \Exception('PHP 7.2+ is need to run the project');
-  }
+	/*
+	 * Exit from APP if the OMLINK requirement aren't meet
+	 */
+	public function DieByOldPhpVersion()
+	{
+		if (version_compare(PHP_VERSION, '7.2') != 1)
+			throw new \Exception('PHP 7.2+ is need to run the project');
+	}
 
-  /**
-   * Check if a port server is opened, return $errno code of fsockopen function
-   *
-   * @param string $ip
-   * @param int $port
-   * @param int $timeout_sec
-   * @return int
-   */
-  function isServerAlive(string $ip, int $port, int $timeout_sec = 5): int
-  {
-    try {
-      @fclose($sck = @fsockopen($ip, $port, $errno, $errstr, $timeout_sec));
-    } catch (\Exception $e) {
-      die($e->getMessage());
-    }
-    return $errno;
-  }
+	/**
+	 * Check if a port server is opened, return $errno code of fsockopen function
+	 *
+	 * @param string $ip
+	 * @param int $port
+	 * @param int $timeout_sec
+	 * @return int
+	 */
+	function isServerAlive(string $ip, int $port, int $timeout_sec = 5): int
+	{
+		try {
+			@fclose($sck = @fsockopen($ip, $port, $errno, $errstr, $timeout_sec));
+		} catch (\Exception $e) {
+			die($e->getMessage());
+		}
+		return $errno;
+	}
 }

+ 99 - 99
src/OpenMind/System/PluginStrategy.php

@@ -15,28 +15,28 @@ namespace OpenMind\System;
  */
 interface IPluginStrategy
 {
-  public function __construct();
-
-  /**
-   * Class version
-   * @return string
-   */
-  public function getVersion(): string;
-
-  /**
-   * Class name
-   * @return string
-   */
-  public function getName(): string;
-
-  /**
-   * Set method route
-   *
-   * @param array|string $pattern
-   * @param string $handler
-   * @return mixed
-   */
-  public function AddRoute($pattern, string $handler);
+	public function __construct();
+
+	/**
+	 * Class version
+	 * @return string
+	 */
+	public function getVersion(): string;
+
+	/**
+	 * Class name
+	 * @return string
+	 */
+	public function getName(): string;
+
+	/**
+	 * Set method route
+	 *
+	 * @param array|string $pattern
+	 * @param string $handler
+	 * @return mixed
+	 */
+	public function AddRoute($pattern, string $handler);
 
 }
 
@@ -47,81 +47,81 @@ interface IPluginStrategy
  */
 class PluginStrategy implements IPluginStrategy
 {
-  public function __construct()
-  {
-    throw new \Exception("Plugin " . $this->getName() . ' doesn\'t have a __constructor() function. Please provide one.');
-  }
-
-  /**
-   * Return default version for plugins that doesn't have one
-   *
-   * @return string
-   */
-  public function getVersion(): string
-  {
-    return '1.0';
-  }
-
-  /**
-   * Return Class name, useful when a list of installed plugins is need
-   *
-   * @return string
-   */
-  public function getName(): string
-  {
-    return get_class($this);
-  }
-
-  /**
-   * Add URL routing to the Route chain
-   *
-   * @param array|string $pattern
-   * @param string $handler
-   */
-  public function AddRoute($pattern, string $handler)
-  {
-    global $f3;
-    $f3->route($pattern, $handler, 0);  // TTL 60s
-  }
-
-  /**
-   * Add menu to application for the plugin, if another menu with same $menuName is present, the last added has priority on other.
-   *
-   * @param string $menuName Name of menu to add
-   * @param array $options the struct of OMLink Menu
-   *
-   * <br/><br/>
-   * [<br/>
-   * &nbsp;&nbsp;'menu_name' => 'Bind',<br/>
-   * &nbsp;&nbsp;'url' => '/bind',<br/>
-   * &nbsp;&nbsp;'isDisabled' => false<br/>
-   * ]
-   */
-  public function AddMenuItem(string $menuName, array $options)
-  {
-    global $f3;
-
-    $defaults = [
-      'url' => '',
-      'isDisabled' => false,
-      'image' => '',
-      'permissionName' => null,
-      'order' => 99999
-    ];
-
-    $newMenu = array_merge($defaults, $options);
-
-    $globalMenuUpdated = $f3->get('GLOBALMENU');
-    $globalMenuUpdated[$menuName] = $newMenu;
-
-    // If user logged check permission
-    $user = User::Restore();
-    if (!$user->dry()) {
-      $hasMenuPermissionRequirements = !is_null($newMenu['permissionName']);
-
-      if (!$hasMenuPermissionRequirements || ($hasMenuPermissionRequirements && $user->hasPermission($newMenu['permissionName']))) {
-        $f3->set('GLOBALMENU', $globalMenuUpdated);
-      }
-    }
-  }
+	public function __construct()
+	{
+		throw new \Exception("Plugin " . $this->getName() . ' doesn\'t have a __constructor() function. Please provide one.');
+	}
+
+	/**
+	 * Return Class name, useful when a list of installed plugins is need
+	 *
+	 * @return string
+	 */
+	public function getName(): string
+	{
+		return get_class($this);
+	}
+
+	/**
+	 * Return default version for plugins that doesn't have one
+	 *
+	 * @return string
+	 */
+	public function getVersion(): string
+	{
+		return '1.0';
+	}
+
+	/**
+	 * Add URL routing to the Route chain
+	 *
+	 * @param array|string $pattern
+	 * @param string $handler
+	 */
+	public function AddRoute($pattern, string $handler)
+	{
+		global $f3;
+		$f3->route($pattern, $handler, 0);  // TTL 60s
+	}
+
+	/**
+	 * Add menu to application for the plugin, if another menu with same $menuName is present, the last added has priority on other.
+	 *
+	 * @param string $menuName Name of menu to add
+	 * @param array $options the struct of OMLink Menu
+	 *
+	 * <br/><br/>
+	 * [<br/>
+	 * &nbsp;&nbsp;'menu_name' => 'Bind',<br/>
+	 * &nbsp;&nbsp;'url' => '/bind',<br/>
+	 * &nbsp;&nbsp;'isDisabled' => false<br/>
+	 * ]
+	 */
+	public function AddMenuItem(string $menuName, array $options)
+	{
+		global $f3;
+
+		$defaults = [
+			'url' => '',
+			'isDisabled' => false,
+			'image' => '',
+			'permissionName' => null,
+			'order' => 99999
+		];
+
+		$newMenu = array_merge($defaults, $options);
+
+		$globalMenuUpdated = $f3->get('GLOBALMENU');
+		$globalMenuUpdated[$menuName] = $newMenu;
+
+		// If user logged check permission
+		$user = User::Restore();
+		if (!$user->dry()) {
+			$hasMenuPermissionRequirements = !is_null($newMenu['permissionName']);
+
+			if (!$hasMenuPermissionRequirements || ($hasMenuPermissionRequirements && $user->hasPermission($newMenu['permissionName']))) {
+				$f3->set('GLOBALMENU', $globalMenuUpdated);
+			}
+		}
+	}
 }

+ 57 - 56
src/OpenMind/System/QueueSystem.php

@@ -12,69 +12,70 @@ use DB\SQL\Mapper;
 
 class QueueSystem extends Mapper
 {
-  private $f3;
-  private $serviceName;
+	private $f3;
+	private $serviceName;
 
-  // Used internally
-  private $initLoad;
+	// Used internally
+	private $initLoad;
 
-  public function __construct(string $serviceName)
-  {
-    global $f3;
-    $this->f3 = $f3;
+	public function __construct(string $serviceName)
+	{
+		global $f3;
+		$this->f3 = $f3;
 
-    parent::__construct($f3->get('DB'), 'queuesystem');
+		parent::__construct($f3->get('DB'), 'queuesystem');
 
-    $this->serviceName = $serviceName;
-  }
+		$this->serviceName = $serviceName;
+	}
 
-  /**
-   * Send object to <$serviceName>.
-   * send() serialize $obj before send to queue
-   *
-   * @param $obj
-   */
-  public function send($obj)
-  {
-    $serializedObject = serialize($obj);
-    $this->reset();
-    $this->servicename = $this->serviceName;
-    $this->command = base64_encode($serializedObject);
-    $this->save();
-  }
+	/**
+	 * Send object to <$serviceName>.
+	 * send() serialize $obj before send to queue
+	 *
+	 * @param $obj
+	 */
+	public function send($obj)
+	{
+		$serializedObject = serialize($obj);
+		$this->reset();
+		$this->servicename = $this->serviceName;
+		$this->command = base64_encode($serializedObject);
+		$this->save();
+	}
 
-  /**
-   * Retrieve and unserialize current object
-   *
-   * @return mixed
-   */
-  public function getCommandObject() {
-    $decodedObj = base64_decode($this->command);
-    $obj = unserialize($decodedObj);
-    return $obj;
-  }
+	/**
+	 * Retrieve and unserialize current object
+	 *
+	 * @return mixed
+	 */
+	public function getCommandObject()
+	{
+		$decodedObj = base64_decode($this->command);
+		$obj = unserialize($decodedObj);
+		return $obj;
+	}
 
-  /**
-   * Retrieve messages
-   *
-   * @return array|FALSE
-   */
-  public function check()
-  {
-    if (!$this->initLoad) {
-      $this->initLoad = true;
-      $this->load(['servicename=?', $this->serviceName]);
-    }
-    return $this->dry();
-  }
+	/**
+	 * Retrieve messages
+	 *
+	 * @return array|FALSE
+	 */
+	public function check()
+	{
+		if (!$this->initLoad) {
+			$this->initLoad = true;
+			$this->load(['servicename=?', $this->serviceName]);
+		}
+		return $this->dry();
+	}
 
-  /**
-   * Delete all messages of <$serviceName>
-   */
-  public function deleteAll()
-  {
-    $this->reset();
-    $this->erase(['servicename=?', $this->serviceName]);
-  }
+	/**
+	 * Delete all messages of <$serviceName>
+	 */
+	public function deleteAll()
+	{
+		$this->reset();
+		$this->erase(['servicename=?', $this->serviceName]);
+	}
 
 }

+ 31 - 31
src/OpenMind/System/Soap.php

@@ -12,37 +12,37 @@ use SoapFault;
 
 class Soap extends \SoapClient
 {
-  private $ws_url;
+	private $ws_url;
 
-  /**
-   * Soap easy constructor.
-   * @param mixed $wsdl Ex.: http://<ip_or_hostname_server>/<service_name>.asmx
-   */
-  public function __construct(string $ws_url)
-  {
-    $this->ws_url = $ws_url;
-    $options = array(
-      'trace' => true,
-      'exceptions' => true,
-      'cache_wsdl' => false,
-    );
-    parent::__construct("{$ws_url}?wsdl", $options);
-  }
+	/**
+	 * Soap easy constructor.
+	 * @param mixed $wsdl Ex.: http://<ip_or_hostname_server>/<service_name>.asmx
+	 */
+	public function __construct(string $ws_url)
+	{
+		$this->ws_url = $ws_url;
+		$options = array(
+			'trace' => true,
+			'exceptions' => true,
+			'cache_wsdl' => false,
+		);
+		parent::__construct("{$ws_url}?wsdl", $options);
+	}
 
-  /**
-   * Send list to Soap Service
-   *
-   * @param string $xml The xml in string format
-   * @param string $soapaction the SOAPACTION: "http://servizi_xchange.org/ImportLists"
-   * @return string The XML SOAP response or exception error
-   */
-  public function ImportLists(string $xml, string $soapaction): ?string
-  {
-    try {
-      $ret = $this->__doRequest($xml, $this->ws_url, $soapaction, SOAP_1_1);
-    } catch (SoapFault $e) {
-      return $e->getMessage();
-    }
-    return $ret;
-  }
+	/**
+	 * Send list to Soap Service
+	 *
+	 * @param string $xml The xml in string format
+	 * @param string $soapaction the SOAPACTION: "http://servizi_xchange.org/ImportLists"
+	 * @return string The XML SOAP response or exception error
+	 */
+	public function ImportLists(string $xml, string $soapaction): ?string
+	{
+		try {
+			$ret = $this->__doRequest($xml, $this->ws_url, $soapaction, SOAP_1_1);
+		} catch (SoapFault $e) {
+			return $e->getMessage();
+		}
+		return $ret;
+	}
 }

+ 143 - 143
src/OpenMind/System/System.php

@@ -10,149 +10,149 @@ namespace OpenMind\System;
 
 class System extends PluginStrategy
 {
-  /**
-   * Normal F3 session file cache.
-   * Every session will be client related
-   *
-   * @var \Cache
-   */
-  private $cache;
-
-  /**
-   * The shared cache, cache file will be created with prefix 'OMLINK_SHARED_CACHE.xxxxxx' where 'xxxxxx' is the variable name.
-   * Every session will be server related
-   *
-   * @var \Cache
-   */
-  private $sharedCache;
-
-  public function __construct()
-  {
-    global $f3;
-    // Set Error Handler
-    $f3->set('ONERROR', __NAMESPACE__ . '\ErrorHandlers->Handler');
-
-    $this->cache = \Cache::instance();
-
-    $this->sharedCache = new \Cache();
-    $this->sharedCache->load($f3->get('CACHE'), 'OMLINK_SHARED_CACHE');
-
-    // Set Database connection
-    try {
-      $dbMode = (strtolower(PHP_OS_FAMILY) == 'linux') ? TRUE : FALSE;
-      if ($f3->get('CLI')) // from cli, always persistent mode
-        $dbMode = TRUE;
-
-      $db = new \DB\SQL(
-        $f3->get('DSN'),
-        $f3->get('dbuser'),
-        $f3->get('dbpass'),
-        array(
-          \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
-          \PDO::ATTR_PERSISTENT => $dbMode  // To avoid massive new persistent connections due to php-cgi processes
-        ));
-
-      // This fix memory leak in ->exec() and all methods of F3 that use this function like load, find, findone etc...
-      $db->log(FALSE);
-
-      $f3->set('DB', $db);
-    } catch (PDOException $e) {
-      die($e->getMessage());
-    }
-
-    $this->setSystemRoutes();
-
-  }
-
-  private function setSystemRoutes()
-  {
-    $this->AddRoute('GET /api.system.getserverstatus', __NAMESPACE__ . '\System->getServerStatus');
-    $this->AddRoute('POST /api.system.removenotification/@code', __NAMESPACE__ . '\System->NotificationDelete');
-  }
-
-  /**
-   * Get cache cache
-   *
-   * @return \Cache
-   */
-  public function getCache(): \Cache
-  {
-    return $this->cache;
-  }
-
-  public function getSharedCache(): \Cache
-  {
-    return $this->sharedCache;
-  }
-
-  /**
-   * AJAX web service for bell notifications and system checking
-   *
-   * @param $f3
-   */
-  public function getServerStatus($f3)
-  {
-    $qs = new QueueSystem('FindBoxService_isAlive');
-    if (!$qs->check()) {
-      $lastUpdate = time() - $qs->command;
-      if ($lastUpdate > $f3->get('FINDBOXSERVICE.GRACE_PERIOD_SEC')) {
-        $omlNotifications = new Notifications();
-        $omlNotifications->notify(Notifications::FB_NOTALIVE, 'Errore: Servizio di FindBox non disponibile');
-      } else {
-        $omlNotifications = new Notifications();
-        $omlNotifications->Remove(Notifications::FB_NOTALIVE);
-      }
-    }
-
-    $ret = [];
-    $notifications = new Notifications();
-    $notifications->count = 'count(caption)';
-    $sqlGroupBy = array(
-      'order' => 'timestamp DESC',
-      'group' => 'caption'
-    );
-    $ret['notify'] = array_map(array($notifications, 'cast'), $notifications->find(NULL, $sqlGroupBy));
-
-    echo json_encode($ret);
-  }
-
-  public function NotificationDelete($f3, $args)
-  {
-    if ($args['code'] != 0)
-      (new Notifications())->Remove($args['code']);
-    else
-      (new Notifications())->emptyAll();
-
-  }
-
-  /**
-   * Store in F3 cache the session id, usefull for CLI call
-   *
-   * @see System::RestoreWebSession()
-   * @param string $cacheName
-   */
-  public Function StoreWebSession(string $cacheName = 'WEBSESSIONID')
-  {
-    $this->cache->set($cacheName, session_id());
-  }
-
-  /**
-   * Restore the web session for CLI calls
-   *
-   * @see System::StoreWebSession()
-   * @param string $cacheName
-   */
-  public function RestoreWebSession(string $cacheName = 'WEBSESSIONID')
-  {
-    if ($this->cache->get($cacheName)) {
-      $id = $this->cache->get($cacheName);
-      if (isset($_SESSION)) {  // if there is already a session running
-        session_write_close(); // save and close it
-      }
-      session_id($id);
-      session_start();
-    }
-  }
+	/**
+	 * Normal F3 session file cache.
+	 * Every session will be client related
+	 *
+	 * @var \Cache
+	 */
+	private $cache;
+
+	/**
+	 * The shared cache, cache file will be created with prefix 'OMLINK_SHARED_CACHE.xxxxxx' where 'xxxxxx' is the variable name.
+	 * Every session will be server related
+	 *
+	 * @var \Cache
+	 */
+	private $sharedCache;
+
+	public function __construct()
+	{
+		global $f3;
+		// Set Error Handler
+		$f3->set('ONERROR', __NAMESPACE__ . '\ErrorHandlers->Handler');
+
+		$this->cache = \Cache::instance();
+
+		$this->sharedCache = new \Cache();
+		$this->sharedCache->load($f3->get('CACHE'), 'OMLINK_SHARED_CACHE');
+
+		// Set Database connection
+		try {
+			$dbMode = (strtolower(PHP_OS_FAMILY) == 'linux') ? TRUE : FALSE;
+			if ($f3->get('CLI')) // from cli, always persistent mode
+				$dbMode = TRUE;
+
+			$db = new \DB\SQL(
+				$f3->get('DSN'),
+				$f3->get('dbuser'),
+				$f3->get('dbpass'),
+				array(
+					\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
+					\PDO::ATTR_PERSISTENT => $dbMode  // To avoid massive new persistent connections due to php-cgi processes
+				));
+
+			// This fix memory leak in ->exec() and all methods of F3 that use this function like load, find, findone etc...
+			$db->log(FALSE);
+
+			$f3->set('DB', $db);
+		} catch (PDOException $e) {
+			die($e->getMessage());
+		}
+
+		$this->setSystemRoutes();
+
+	}
+
+	private function setSystemRoutes()
+	{
+		$this->AddRoute('GET /api.system.getserverstatus', __NAMESPACE__ . '\System->getServerStatus');
+		$this->AddRoute('POST /api.system.removenotification/@code', __NAMESPACE__ . '\System->NotificationDelete');
+	}
+
+	/**
+	 * Get cache cache
+	 *
+	 * @return \Cache
+	 */
+	public function getCache(): \Cache
+	{
+		return $this->cache;
+	}
+
+	public function getSharedCache(): \Cache
+	{
+		return $this->sharedCache;
+	}
+
+	/**
+	 * AJAX web service for bell notifications and system checking
+	 *
+	 * @param $f3
+	 */
+	public function getServerStatus($f3)
+	{
+		$qs = new QueueSystem('FindBoxService_isAlive');
+		if (!$qs->check()) {
+			$lastUpdate = time() - $qs->command;
+			if ($lastUpdate > $f3->get('FINDBOXSERVICE.GRACE_PERIOD_SEC')) {
+				$omlNotifications = new Notifications();
+				$omlNotifications->notify(Notifications::FB_NOTALIVE, 'Errore: Servizio di FindBox non disponibile');
+			} else {
+				$omlNotifications = new Notifications();
+				$omlNotifications->Remove(Notifications::FB_NOTALIVE);
+			}
+		}
+
+		$ret = [];
+		$notifications = new Notifications();
+		$notifications->count = 'count(caption)';
+		$sqlGroupBy = array(
+			'order' => 'timestamp DESC',
+			'group' => 'caption'
+		);
+		$ret['notify'] = array_map(array($notifications, 'cast'), $notifications->find(NULL, $sqlGroupBy));
+
+		echo json_encode($ret);
+	}
+
+	public function NotificationDelete($f3, $args)
+	{
+		if ($args['code'] != 0)
+			(new Notifications())->Remove($args['code']);
+		else
+			(new Notifications())->emptyAll();
+
+	}
+
+	/**
+	 * Store in F3 cache the session id, usefull for CLI call
+	 *
+	 * @see System::RestoreWebSession()
+	 * @param string $cacheName
+	 */
+	public Function StoreWebSession(string $cacheName = 'WEBSESSIONID')
+	{
+		$this->cache->set($cacheName, session_id());
+	}
+
+	/**
+	 * Restore the web session for CLI calls
+	 *
+	 * @see System::StoreWebSession()
+	 * @param string $cacheName
+	 */
+	public function RestoreWebSession(string $cacheName = 'WEBSESSIONID')
+	{
+		if ($this->cache->get($cacheName)) {
+			$id = $this->cache->get($cacheName);
+			if (isset($_SESSION)) {  // if there is already a session running
+				session_write_close(); // save and close it
+			}
+			session_id($id);
+			session_start();
+		}
+	}
 }
 
 /** @var System $System * */

+ 39 - 39
src/OpenMind/System/UserRoles.php

@@ -18,48 +18,48 @@ namespace OpenMind\System;
  */
 class UserRoles
 {
-  public function __construct()
-  {
-    global $f3;
-    // Define global array is doesn't exists
-    if (is_null($f3->get('USERROLES')))
-      $f3->set('USERROLES', array());
-  }
+	public function __construct()
+	{
+		global $f3;
+		// Define global array is doesn't exists
+		if (is_null($f3->get('USERROLES')))
+			$f3->set('USERROLES', array());
+	}
 
-  /**
-   * Get all defined user roles
-   *
-   * @return array
-   */
-  public static function getAllRoles(): array
-  {
-    global $f3;
-    return $f3->get('USERROLES');
-  }
+	/**
+	 * Get all defined user roles
+	 *
+	 * @return array
+	 */
+	public static function getAllRoles(): array
+	{
+		global $f3;
+		return $f3->get('USERROLES');
+	}
 
-  /**
-   * Retrieve permission value
-   *
-   * @param string $permissionName
-   * @return mixed
-   */
-  public function get(string $permissionName)
-  {
-    global $f3;
-    return $f3->get('USERROLES')[$permissionName];
-  }
+	/**
+	 * Retrieve permission value
+	 *
+	 * @param string $permissionName
+	 * @return mixed
+	 */
+	public function get(string $permissionName)
+	{
+		global $f3;
+		return $f3->get('USERROLES')[$permissionName];
+	}
 
-  /**
-   * Add new permission to roles
-   *
-   * @param string $permissionName
-   */
-  public function add(string $permissionName)
-  {
-    global $f3;
+	/**
+	 * Add new permission to roles
+	 *
+	 * @param string $permissionName
+	 */
+	public function add(string $permissionName)
+	{
+		global $f3;
 
-    $roles = &$f3->ref('USERROLES');
+		$roles = &$f3->ref('USERROLES');
 
-    array_push($roles, $permissionName);
-  }
+		array_push($roles, $permissionName);
+	}
 }

+ 4 - 5
src/OpenMind/Web/Controller.php

@@ -26,14 +26,13 @@ class Controller
 		$this->sanitizedPostRequest = $f3->clean($f3->get('POST'));
 		$this->dbHandle = $f3->get('DB');
 
-		if (!$f3->exists('SESSION.user') && !in_array($f3->get('PATTERN'), ['/loginform', '/'])) {
+		if (!$f3->exists('SESSION.user') && !in_array($f3->get('PATTERN'), ['/loginform', '/admin', '/'])) {
 			$f3->reroute('/');
 			return;
 		}
 
 		if ($f3->exists('SESSION.user')) {
 			$f3->set('USER', User::Restore());
-
 		}
 
 		return;
@@ -53,13 +52,13 @@ class Controller
 	 * Use setTimeout to request a change url
 	 *
 	 * @param string $url to change to
-	 * @param int $msdelay
+	 * @param int $msDelay
 	 */
-	protected function setRedirect(string $url, int $msdelay)
+	protected function setRedirect(string $url, int $msDelay)
 	{
 		global $f3;
 
 		$f3->set('REQ_REDIRECT', $url);
-		$f3->set('REQ_REDIRECT_MS', $msdelay);
+		$f3->set('REQ_REDIRECT_MS', $msDelay);
 	}
 }

+ 2870 - 2811
src/Picqer/Barcode/BarcodeGenerator.php

@@ -38,2815 +38,2874 @@ use Picqer\Barcode\Exceptions\UnknownTypeException;
 
 abstract class BarcodeGenerator
 {
-    const TYPE_CODE_39 = 'C39';
-    const TYPE_CODE_39_CHECKSUM = 'C39+';
-    const TYPE_CODE_39E = 'C39E';
-    const TYPE_CODE_39E_CHECKSUM = 'C39E+';
-    const TYPE_CODE_93 = 'C93';
-    const TYPE_STANDARD_2_5 = 'S25';
-    const TYPE_STANDARD_2_5_CHECKSUM = 'S25+';
-    const TYPE_INTERLEAVED_2_5 = 'I25';
-    const TYPE_INTERLEAVED_2_5_CHECKSUM = 'I25+';
-    const TYPE_CODE_128 = 'C128';
-    const TYPE_CODE_128_A = 'C128A';
-    const TYPE_CODE_128_B = 'C128B';
-    const TYPE_CODE_128_C = 'C128C';
-    const TYPE_EAN_2 = 'EAN2';
-    const TYPE_EAN_5 = 'EAN5';
-    const TYPE_EAN_8 = 'EAN8';
-    const TYPE_EAN_13 = 'EAN13';
-    const TYPE_UPC_A = 'UPCA';
-    const TYPE_UPC_E = 'UPCE';
-    const TYPE_MSI = 'MSI';
-    const TYPE_MSI_CHECKSUM = 'MSI+';
-    const TYPE_POSTNET = 'POSTNET';
-    const TYPE_PLANET = 'PLANET';
-    const TYPE_RMS4CC = 'RMS4CC';
-    const TYPE_KIX = 'KIX';
-    const TYPE_IMB = 'IMB';
-    const TYPE_CODABAR = 'CODABAR';
-    const TYPE_CODE_11 = 'CODE11';
-    const TYPE_PHARMA_CODE = 'PHARMA';
-    const TYPE_PHARMA_CODE_TWO_TRACKS = 'PHARMA2T';
-
-    /**
-     * Get the barcode data
-     *
-     * @param string $code code to print
-     * @param string $type type of barcode
-     * @return array barcode array
-     * @public
-     */
-    protected function getBarcodeData($code, $type)
-    {
-        switch (strtoupper($type)) {
-            case self::TYPE_CODE_39: { // CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
-                $arrcode = $this->barcode_code39($code, false, false);
-                break;
-            }
-            case self::TYPE_CODE_39_CHECKSUM: { // CODE 39 with checksum
-                $arrcode = $this->barcode_code39($code, false, true);
-                break;
-            }
-            case self::TYPE_CODE_39E: { // CODE 39 EXTENDED
-                $arrcode = $this->barcode_code39($code, true, false);
-                break;
-            }
-            case self::TYPE_CODE_39E_CHECKSUM: { // CODE 39 EXTENDED + CHECKSUM
-                $arrcode = $this->barcode_code39($code, true, true);
-                break;
-            }
-            case self::TYPE_CODE_93: { // CODE 93 - USS-93
-                $arrcode = $this->barcode_code93($code);
-                break;
-            }
-            case self::TYPE_STANDARD_2_5: { // Standard 2 of 5
-                $arrcode = $this->barcode_s25($code, false);
-                break;
-            }
-            case self::TYPE_STANDARD_2_5_CHECKSUM: { // Standard 2 of 5 + CHECKSUM
-                $arrcode = $this->barcode_s25($code, true);
-                break;
-            }
-            case self::TYPE_INTERLEAVED_2_5: { // Interleaved 2 of 5
-                $arrcode = $this->barcode_i25($code, false);
-                break;
-            }
-            case self::TYPE_INTERLEAVED_2_5_CHECKSUM: { // Interleaved 2 of 5 + CHECKSUM
-                $arrcode = $this->barcode_i25($code, true);
-                break;
-            }
-            case self::TYPE_CODE_128: { // CODE 128
-                $arrcode = $this->barcode_c128($code, '');
-                break;
-            }
-            case self::TYPE_CODE_128_A: { // CODE 128 A
-                $arrcode = $this->barcode_c128($code, 'A');
-                break;
-            }
-            case self::TYPE_CODE_128_B: { // CODE 128 B
-                $arrcode = $this->barcode_c128($code, 'B');
-                break;
-            }
-            case self::TYPE_CODE_128_C: { // CODE 128 C
-                $arrcode = $this->barcode_c128($code, 'C');
-                break;
-            }
-            case self::TYPE_EAN_2: { // 2-Digits UPC-Based Extention
-                $arrcode = $this->barcode_eanext($code, 2);
-                break;
-            }
-            case self::TYPE_EAN_5: { // 5-Digits UPC-Based Extention
-                $arrcode = $this->barcode_eanext($code, 5);
-                break;
-            }
-            case self::TYPE_EAN_8: { // EAN 8
-                $arrcode = $this->barcode_eanupc($code, 8);
-                break;
-            }
-            case self::TYPE_EAN_13: { // EAN 13
-                $arrcode = $this->barcode_eanupc($code, 13);
-                break;
-            }
-            case self::TYPE_UPC_A: { // UPC-A
-                $arrcode = $this->barcode_eanupc($code, 12);
-                break;
-            }
-            case self::TYPE_UPC_E: { // UPC-E
-                $arrcode = $this->barcode_eanupc($code, 6);
-                break;
-            }
-            case self::TYPE_MSI: { // MSI (Variation of Plessey code)
-                $arrcode = $this->barcode_msi($code, false);
-                break;
-            }
-            case self::TYPE_MSI_CHECKSUM: { // MSI + CHECKSUM (modulo 11)
-                $arrcode = $this->barcode_msi($code, true);
-                break;
-            }
-            case self::TYPE_POSTNET: { // POSTNET
-                $arrcode = $this->barcode_postnet($code, false);
-                break;
-            }
-            case self::TYPE_PLANET: { // PLANET
-                $arrcode = $this->barcode_postnet($code, true);
-                break;
-            }
-            case self::TYPE_RMS4CC: { // RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)
-                $arrcode = $this->barcode_rms4cc($code, false);
-                break;
-            }
-            case self::TYPE_KIX: { // KIX (Klant index - Customer index)
-                $arrcode = $this->barcode_rms4cc($code, true);
-                break;
-            }
-            case self::TYPE_IMB: { // IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
-                $arrcode = $this->barcode_imb($code);
-                break;
-            }
-            case self::TYPE_CODABAR: { // CODABAR
-                $arrcode = $this->barcode_codabar($code);
-                break;
-            }
-            case self::TYPE_CODE_11: { // CODE 11
-                $arrcode = $this->barcode_code11($code);
-                break;
-            }
-            case self::TYPE_PHARMA_CODE: { // PHARMACODE
-                $arrcode = $this->barcode_pharmacode($code);
-                break;
-            }
-            case self::TYPE_PHARMA_CODE_TWO_TRACKS: { // PHARMACODE TWO-TRACKS
-                $arrcode = $this->barcode_pharmacode2t($code);
-                break;
-            }
-            default: {
-                throw new UnknownTypeException();
-                break;
-            }
-        }
-
-        if ( ! isset($arrcode['maxWidth'])) {
-            $arrcode = $this->convertBarcodeArrayToNewStyle($arrcode);
-        }
-
-        return $arrcode;
-    }
-
-    /**
-     * CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
-     * General-purpose code in very wide use world-wide
-     *
-     * @param $code (string) code to represent.
-     * @param $extended (boolean) if true uses the extended mode.
-     * @param $checksum (boolean) if true add a checksum to the code.
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_code39($code, $extended = false, $checksum = false)
-    {
-        $chr = [];
-        $chr['0'] = '111331311';
-        $chr['1'] = '311311113';
-        $chr['2'] = '113311113';
-        $chr['3'] = '313311111';
-        $chr['4'] = '111331113';
-        $chr['5'] = '311331111';
-        $chr['6'] = '113331111';
-        $chr['7'] = '111311313';
-        $chr['8'] = '311311311';
-        $chr['9'] = '113311311';
-        $chr['A'] = '311113113';
-        $chr['B'] = '113113113';
-        $chr['C'] = '313113111';
-        $chr['D'] = '111133113';
-        $chr['E'] = '311133111';
-        $chr['F'] = '113133111';
-        $chr['G'] = '111113313';
-        $chr['H'] = '311113311';
-        $chr['I'] = '113113311';
-        $chr['J'] = '111133311';
-        $chr['K'] = '311111133';
-        $chr['L'] = '113111133';
-        $chr['M'] = '313111131';
-        $chr['N'] = '111131133';
-        $chr['O'] = '311131131';
-        $chr['P'] = '113131131';
-        $chr['Q'] = '111111333';
-        $chr['R'] = '311111331';
-        $chr['S'] = '113111331';
-        $chr['T'] = '111131331';
-        $chr['U'] = '331111113';
-        $chr['V'] = '133111113';
-        $chr['W'] = '333111111';
-        $chr['X'] = '131131113';
-        $chr['Y'] = '331131111';
-        $chr['Z'] = '133131111';
-        $chr['-'] = '131111313';
-        $chr['.'] = '331111311';
-        $chr[' '] = '133111311';
-        $chr['$'] = '131313111';
-        $chr['/'] = '131311131';
-        $chr['+'] = '131113131';
-        $chr['%'] = '111313131';
-        $chr['*'] = '131131311';
-
-        $code = strtoupper($code);
-
-        if ($extended) {
-            // extended mode
-            $code = $this->encode_code39_ext($code);
-        }
-
-        if ($checksum) {
-            // checksum
-            $code .= $this->checksum_code39($code);
-        }
-
-        // add start and stop codes
-        $code = '*' . $code . '*';
-
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
-        $k = 0;
-        $clen = strlen($code);
-        for ($i = 0; $i < $clen; ++$i) {
-            $char = $code{$i};
-            if ( ! isset($chr[$char])) {
-                throw new InvalidCharacterException('Char ' . $char . ' is unsupported');
-            }
-            for ($j = 0; $j < 9; ++$j) {
-                if (($j % 2) == 0) {
-                    $t = true; // bar
-                } else {
-                    $t = false; // space
-                }
-                $w = $chr[$char]{$j};
-                $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
-                $bararray['maxw'] += $w;
-                ++$k;
-            }
-            // intercharacter gap
-            $bararray['bcode'][$k] = array('t' => false, 'w' => 1, 'h' => 1, 'p' => 0);
-            $bararray['maxw'] += 1;
-            ++$k;
-        }
-
-        return $bararray;
-    }
-
-    /**
-     * Encode a string to be used for CODE 39 Extended mode.
-     *
-     * @param string $code code to represent.
-     * @return bool|string encoded string.
-     * @protected
-     */
-    protected function encode_code39_ext($code)
-    {
-        $encode = array(
-            chr(0)   => '%U',
-            chr(1)   => '$A',
-            chr(2)   => '$B',
-            chr(3)   => '$C',
-            chr(4)   => '$D',
-            chr(5)   => '$E',
-            chr(6)   => '$F',
-            chr(7)   => '$G',
-            chr(8)   => '$H',
-            chr(9)   => '$I',
-            chr(10)  => '$J',
-            chr(11)  => '£K',
-            chr(12)  => '$L',
-            chr(13)  => '$M',
-            chr(14)  => '$N',
-            chr(15)  => '$O',
-            chr(16)  => '$P',
-            chr(17)  => '$Q',
-            chr(18)  => '$R',
-            chr(19)  => '$S',
-            chr(20)  => '$T',
-            chr(21)  => '$U',
-            chr(22)  => '$V',
-            chr(23)  => '$W',
-            chr(24)  => '$X',
-            chr(25)  => '$Y',
-            chr(26)  => '$Z',
-            chr(27)  => '%A',
-            chr(28)  => '%B',
-            chr(29)  => '%C',
-            chr(30)  => '%D',
-            chr(31)  => '%E',
-            chr(32)  => ' ',
-            chr(33)  => '/A',
-            chr(34)  => '/B',
-            chr(35)  => '/C',
-            chr(36)  => '/D',
-            chr(37)  => '/E',
-            chr(38)  => '/F',
-            chr(39)  => '/G',
-            chr(40)  => '/H',
-            chr(41)  => '/I',
-            chr(42)  => '/J',
-            chr(43)  => '/K',
-            chr(44)  => '/L',
-            chr(45)  => '-',
-            chr(46)  => '.',
-            chr(47)  => '/O',
-            chr(48)  => '0',
-            chr(49)  => '1',
-            chr(50)  => '2',
-            chr(51)  => '3',
-            chr(52)  => '4',
-            chr(53)  => '5',
-            chr(54)  => '6',
-            chr(55)  => '7',
-            chr(56)  => '8',
-            chr(57)  => '9',
-            chr(58)  => '/Z',
-            chr(59)  => '%F',
-            chr(60)  => '%G',
-            chr(61)  => '%H',
-            chr(62)  => '%I',
-            chr(63)  => '%J',
-            chr(64)  => '%V',
-            chr(65)  => 'A',
-            chr(66)  => 'B',
-            chr(67)  => 'C',
-            chr(68)  => 'D',
-            chr(69)  => 'E',
-            chr(70)  => 'F',
-            chr(71)  => 'G',
-            chr(72)  => 'H',
-            chr(73)  => 'I',
-            chr(74)  => 'J',
-            chr(75)  => 'K',
-            chr(76)  => 'L',
-            chr(77)  => 'M',
-            chr(78)  => 'N',
-            chr(79)  => 'O',
-            chr(80)  => 'P',
-            chr(81)  => 'Q',
-            chr(82)  => 'R',
-            chr(83)  => 'S',
-            chr(84)  => 'T',
-            chr(85)  => 'U',
-            chr(86)  => 'V',
-            chr(87)  => 'W',
-            chr(88)  => 'X',
-            chr(89)  => 'Y',
-            chr(90)  => 'Z',
-            chr(91)  => '%K',
-            chr(92)  => '%L',
-            chr(93)  => '%M',
-            chr(94)  => '%N',
-            chr(95)  => '%O',
-            chr(96)  => '%W',
-            chr(97)  => '+A',
-            chr(98)  => '+B',
-            chr(99)  => '+C',
-            chr(100) => '+D',
-            chr(101) => '+E',
-            chr(102) => '+F',
-            chr(103) => '+G',
-            chr(104) => '+H',
-            chr(105) => '+I',
-            chr(106) => '+J',
-            chr(107) => '+K',
-            chr(108) => '+L',
-            chr(109) => '+M',
-            chr(110) => '+N',
-            chr(111) => '+O',
-            chr(112) => '+P',
-            chr(113) => '+Q',
-            chr(114) => '+R',
-            chr(115) => '+S',
-            chr(116) => '+T',
-            chr(117) => '+U',
-            chr(118) => '+V',
-            chr(119) => '+W',
-            chr(120) => '+X',
-            chr(121) => '+Y',
-            chr(122) => '+Z',
-            chr(123) => '%P',
-            chr(124) => '%Q',
-            chr(125) => '%R',
-            chr(126) => '%S',
-            chr(127) => '%T'
-        );
-        $code_ext = '';
-        $clen = strlen($code);
-        for ($i = 0; $i < $clen; ++$i) {
-            if (ord($code{$i}) > 127) {
-                throw new InvalidCharacterException('Only supports till char 127');
-            }
-            $code_ext .= $encode[$code{$i}];
-        }
-
-        return $code_ext;
-    }
-
-    /**
-     * Calculate CODE 39 checksum (modulo 43).
-     *
-     * @param string $code code to represent.
-     * @return string char checksum.
-     * @protected
-     */
-    protected function checksum_code39($code)
-    {
-        $chars = array(
-            '0',
-            '1',
-            '2',
-            '3',
-            '4',
-            '5',
-            '6',
-            '7',
-            '8',
-            '9',
-            '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',
-            '-',
-            '.',
-            ' ',
-            '$',
-            '/',
-            '+',
-            '%'
-        );
-        $sum = 0;
-        $codelength = strlen($code);
-        for ($i = 0; $i < $codelength; ++$i) {
-            $k = array_keys($chars, $code{$i});
-            $sum += $k[0];
-        }
-        $j = ($sum % 43);
-
-        return $chars[$j];
-    }
-
-    /**
-     * CODE 93 - USS-93
-     * Compact code similar to Code 39
-     *
-     * @param $code (string) code to represent.
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_code93($code)
-    {
-        $chr = [];
-        $chr[48] = '131112'; // 0
-        $chr[49] = '111213'; // 1
-        $chr[50] = '111312'; // 2
-        $chr[51] = '111411'; // 3
-        $chr[52] = '121113'; // 4
-        $chr[53] = '121212'; // 5
-        $chr[54] = '121311'; // 6
-        $chr[55] = '111114'; // 7
-        $chr[56] = '131211'; // 8
-        $chr[57] = '141111'; // 9
-        $chr[65] = '211113'; // A
-        $chr[66] = '211212'; // B
-        $chr[67] = '211311'; // C
-        $chr[68] = '221112'; // D
-        $chr[69] = '221211'; // E
-        $chr[70] = '231111'; // F
-        $chr[71] = '112113'; // G
-        $chr[72] = '112212'; // H
-        $chr[73] = '112311'; // I
-        $chr[74] = '122112'; // J
-        $chr[75] = '132111'; // K
-        $chr[76] = '111123'; // L
-        $chr[77] = '111222'; // M
-        $chr[78] = '111321'; // N
-        $chr[79] = '121122'; // O
-        $chr[80] = '131121'; // P
-        $chr[81] = '212112'; // Q
-        $chr[82] = '212211'; // R
-        $chr[83] = '211122'; // S
-        $chr[84] = '211221'; // T
-        $chr[85] = '221121'; // U
-        $chr[86] = '222111'; // V
-        $chr[87] = '112122'; // W
-        $chr[88] = '112221'; // X
-        $chr[89] = '122121'; // Y
-        $chr[90] = '123111'; // Z
-        $chr[45] = '121131'; // -
-        $chr[46] = '311112'; // .
-        $chr[32] = '311211'; //
-        $chr[36] = '321111'; // $
-        $chr[47] = '112131'; // /
-        $chr[43] = '113121'; // +
-        $chr[37] = '211131'; // %
-        $chr[128] = '121221'; // ($)
-        $chr[129] = '311121'; // (/)
-        $chr[130] = '122211'; // (+)
-        $chr[131] = '312111'; // (%)
-        $chr[42] = '111141'; // start-stop
-        $code = strtoupper($code);
-        $encode = array(
-            chr(0)   => chr(131) . 'U',
-            chr(1)   => chr(128) . 'A',
-            chr(2)   => chr(128) . 'B',
-            chr(3)   => chr(128) . 'C',
-            chr(4)   => chr(128) . 'D',
-            chr(5)   => chr(128) . 'E',
-            chr(6)   => chr(128) . 'F',
-            chr(7)   => chr(128) . 'G',
-            chr(8)   => chr(128) . 'H',
-            chr(9)   => chr(128) . 'I',
-            chr(10)  => chr(128) . 'J',
-            chr(11)  => '£K',
-            chr(12)  => chr(128) . 'L',
-            chr(13)  => chr(128) . 'M',
-            chr(14)  => chr(128) . 'N',
-            chr(15)  => chr(128) . 'O',
-            chr(16)  => chr(128) . 'P',
-            chr(17)  => chr(128) . 'Q',
-            chr(18)  => chr(128) . 'R',
-            chr(19)  => chr(128) . 'S',
-            chr(20)  => chr(128) . 'T',
-            chr(21)  => chr(128) . 'U',
-            chr(22)  => chr(128) . 'V',
-            chr(23)  => chr(128) . 'W',
-            chr(24)  => chr(128) . 'X',
-            chr(25)  => chr(128) . 'Y',
-            chr(26)  => chr(128) . 'Z',
-            chr(27)  => chr(131) . 'A',
-            chr(28)  => chr(131) . 'B',
-            chr(29)  => chr(131) . 'C',
-            chr(30)  => chr(131) . 'D',
-            chr(31)  => chr(131) . 'E',
-            chr(32)  => ' ',
-            chr(33)  => chr(129) . 'A',
-            chr(34)  => chr(129) . 'B',
-            chr(35)  => chr(129) . 'C',
-            chr(36)  => chr(129) . 'D',
-            chr(37)  => chr(129) . 'E',
-            chr(38)  => chr(129) . 'F',
-            chr(39)  => chr(129) . 'G',
-            chr(40)  => chr(129) . 'H',
-            chr(41)  => chr(129) . 'I',
-            chr(42)  => chr(129) . 'J',
-            chr(43)  => chr(129) . 'K',
-            chr(44)  => chr(129) . 'L',
-            chr(45)  => '-',
-            chr(46)  => '.',
-            chr(47)  => chr(129) . 'O',
-            chr(48)  => '0',
-            chr(49)  => '1',
-            chr(50)  => '2',
-            chr(51)  => '3',
-            chr(52)  => '4',
-            chr(53)  => '5',
-            chr(54)  => '6',
-            chr(55)  => '7',
-            chr(56)  => '8',
-            chr(57)  => '9',
-            chr(58)  => chr(129) . 'Z',
-            chr(59)  => chr(131) . 'F',
-            chr(60)  => chr(131) . 'G',
-            chr(61)  => chr(131) . 'H',
-            chr(62)  => chr(131) . 'I',
-            chr(63)  => chr(131) . 'J',
-            chr(64)  => chr(131) . 'V',
-            chr(65)  => 'A',
-            chr(66)  => 'B',
-            chr(67)  => 'C',
-            chr(68)  => 'D',
-            chr(69)  => 'E',
-            chr(70)  => 'F',
-            chr(71)  => 'G',
-            chr(72)  => 'H',
-            chr(73)  => 'I',
-            chr(74)  => 'J',
-            chr(75)  => 'K',
-            chr(76)  => 'L',
-            chr(77)  => 'M',
-            chr(78)  => 'N',
-            chr(79)  => 'O',
-            chr(80)  => 'P',
-            chr(81)  => 'Q',
-            chr(82)  => 'R',
-            chr(83)  => 'S',
-            chr(84)  => 'T',
-            chr(85)  => 'U',
-            chr(86)  => 'V',
-            chr(87)  => 'W',
-            chr(88)  => 'X',
-            chr(89)  => 'Y',
-            chr(90)  => 'Z',
-            chr(91)  => chr(131) . 'K',
-            chr(92)  => chr(131) . 'L',
-            chr(93)  => chr(131) . 'M',
-            chr(94)  => chr(131) . 'N',
-            chr(95)  => chr(131) . 'O',
-            chr(96)  => chr(131) . 'W',
-            chr(97)  => chr(130) . 'A',
-            chr(98)  => chr(130) . 'B',
-            chr(99)  => chr(130) . 'C',
-            chr(100) => chr(130) . 'D',
-            chr(101) => chr(130) . 'E',
-            chr(102) => chr(130) . 'F',
-            chr(103) => chr(130) . 'G',
-            chr(104) => chr(130) . 'H',
-            chr(105) => chr(130) . 'I',
-            chr(106) => chr(130) . 'J',
-            chr(107) => chr(130) . 'K',
-            chr(108) => chr(130) . 'L',
-            chr(109) => chr(130) . 'M',
-            chr(110) => chr(130) . 'N',
-            chr(111) => chr(130) . 'O',
-            chr(112) => chr(130) . 'P',
-            chr(113) => chr(130) . 'Q',
-            chr(114) => chr(130) . 'R',
-            chr(115) => chr(130) . 'S',
-            chr(116) => chr(130) . 'T',
-            chr(117) => chr(130) . 'U',
-            chr(118) => chr(130) . 'V',
-            chr(119) => chr(130) . 'W',
-            chr(120) => chr(130) . 'X',
-            chr(121) => chr(130) . 'Y',
-            chr(122) => chr(130) . 'Z',
-            chr(123) => chr(131) . 'P',
-            chr(124) => chr(131) . 'Q',
-            chr(125) => chr(131) . 'R',
-            chr(126) => chr(131) . 'S',
-            chr(127) => chr(131) . 'T'
-        );
-        $code_ext = '';
-        $clen = strlen($code);
-        for ($i = 0; $i < $clen; ++$i) {
-            if (ord($code{$i}) > 127) {
-                throw new InvalidCharacterException('Only supports till char 127');
-            }
-            $code_ext .= $encode[$code{$i}];
-        }
-        // checksum
-        $code_ext .= $this->checksum_code93($code_ext);
-        // add start and stop codes
-        $code = '*' . $code_ext . '*';
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
-        $k = 0;
-        $clen = strlen($code);
-        for ($i = 0; $i < $clen; ++$i) {
-            $char = ord($code{$i});
-            if ( ! isset($chr[$char])) {
-                throw new InvalidCharacterException('Char ' . $char . ' is unsupported');
-            }
-            for ($j = 0; $j < 6; ++$j) {
-                if (($j % 2) == 0) {
-                    $t = true; // bar
-                } else {
-                    $t = false; // space
-                }
-                $w = $chr[$char]{$j};
-                $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
-                $bararray['maxw'] += $w;
-                ++$k;
-            }
-        }
-        $bararray['bcode'][$k] = array('t' => true, 'w' => 1, 'h' => 1, 'p' => 0);
-        $bararray['maxw'] += 1;
-
-        return $bararray;
-    }
-
-    /**
-     * Calculate CODE 93 checksum (modulo 47).
-     *
-     * @param $code (string) code to represent.
-     * @return string checksum code.
-     * @protected
-     */
-    protected function checksum_code93($code)
-    {
-        $chars = array(
-            '0',
-            '1',
-            '2',
-            '3',
-            '4',
-            '5',
-            '6',
-            '7',
-            '8',
-            '9',
-            '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',
-            '-',
-            '.',
-            ' ',
-            '$',
-            '/',
-            '+',
-            '%',
-            '<',
-            '=',
-            '>',
-            '?'
-        );
-        // translate special characters
-        $code = strtr($code, chr(128) . chr(131) . chr(129) . chr(130), '<=>?');
-        $len = strlen($code);
-        // calculate check digit C
-        $p = 1;
-        $check = 0;
-        for ($i = ($len - 1); $i >= 0; --$i) {
-            $k = array_keys($chars, $code{$i});
-            $check += ($k[0] * $p);
-            ++$p;
-            if ($p > 20) {
-                $p = 1;
-            }
-        }
-        $check %= 47;
-        $c = $chars[$check];
-        $code .= $c;
-        // calculate check digit K
-        $p = 1;
-        $check = 0;
-        for ($i = $len; $i >= 0; --$i) {
-            $k = array_keys($chars, $code{$i});
-            $check += ($k[0] * $p);
-            ++$p;
-            if ($p > 15) {
-                $p = 1;
-            }
-        }
-        $check %= 47;
-        $k = $chars[$check];
-        $checksum = $c . $k;
-        // resto respecial characters
-        $checksum = strtr($checksum, '<=>?', chr(128) . chr(131) . chr(129) . chr(130));
-
-        return $checksum;
-    }
-
-    /**
-     * Checksum for standard 2 of 5 barcodes.
-     *
-     * @param $code (string) code to process.
-     * @return int checksum.
-     * @protected
-     */
-    protected function checksum_s25($code)
-    {
-        $len = strlen($code);
-        $sum = 0;
-        for ($i = 0; $i < $len; $i += 2) {
-            $sum += $code{$i};
-        }
-        $sum *= 3;
-        for ($i = 1; $i < $len; $i += 2) {
-            $sum += ($code{$i});
-        }
-        $r = $sum % 10;
-        if ($r > 0) {
-            $r = (10 - $r);
-        }
-
-        return $r;
-    }
-
-    /**
-     * MSI.
-     * Variation of Plessey code, with similar applications
-     * Contains digits (0 to 9) and encodes the data only in the width of bars.
-     *
-     * @param $code (string) code to represent.
-     * @param $checksum (boolean) if true add a checksum to the code (modulo 11)
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_msi($code, $checksum = false)
-    {
-        $chr['0'] = '100100100100';
-        $chr['1'] = '100100100110';
-        $chr['2'] = '100100110100';
-        $chr['3'] = '100100110110';
-        $chr['4'] = '100110100100';
-        $chr['5'] = '100110100110';
-        $chr['6'] = '100110110100';
-        $chr['7'] = '100110110110';
-        $chr['8'] = '110100100100';
-        $chr['9'] = '110100100110';
-        $chr['A'] = '110100110100';
-        $chr['B'] = '110100110110';
-        $chr['C'] = '110110100100';
-        $chr['D'] = '110110100110';
-        $chr['E'] = '110110110100';
-        $chr['F'] = '110110110110';
-        if ($checksum) {
-            // add checksum
-            $clen = strlen($code);
-            $p = 2;
-            $check = 0;
-            for ($i = ($clen - 1); $i >= 0; --$i) {
-                $check += (hexdec($code{$i}) * $p);
-                ++$p;
-                if ($p > 7) {
-                    $p = 2;
-                }
-            }
-            $check %= 11;
-            if ($check > 0) {
-                $check = 11 - $check;
-            }
-            $code .= $check;
-        }
-        $seq = '110'; // left guard
-        $clen = strlen($code);
-        for ($i = 0; $i < $clen; ++$i) {
-            $digit = $code{$i};
-            if ( ! isset($chr[$digit])) {
-                throw new InvalidCharacterException('Char ' . $digit . ' is unsupported');
-            }
-            $seq .= $chr[$digit];
-        }
-        $seq .= '1001'; // right guard
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
-
-        return $this->binseq_to_array($seq, $bararray);
-    }
-
-    /**
-     * Standard 2 of 5 barcodes.
-     * Used in airline ticket marking, photofinishing
-     * Contains digits (0 to 9) and encodes the data only in the width of bars.
-     *
-     * @param $code (string) code to represent.
-     * @param $checksum (boolean) if true add a checksum to the code
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_s25($code, $checksum = false)
-    {
-        $chr['0'] = '10101110111010';
-        $chr['1'] = '11101010101110';
-        $chr['2'] = '10111010101110';
-        $chr['3'] = '11101110101010';
-        $chr['4'] = '10101110101110';
-        $chr['5'] = '11101011101010';
-        $chr['6'] = '10111011101010';
-        $chr['7'] = '10101011101110';
-        $chr['8'] = '10101110111010';
-        $chr['9'] = '10111010111010';
-        if ($checksum) {
-            // add checksum
-            $code .= $this->checksum_s25($code);
-        }
-        if ((strlen($code) % 2) != 0) {
-            // add leading zero if code-length is odd
-            $code = '0' . $code;
-        }
-        $seq = '11011010';
-        $clen = strlen($code);
-        for ($i = 0; $i < $clen; ++$i) {
-            $digit = $code{$i};
-            if ( ! isset($chr[$digit])) {
-                throw new InvalidCharacterException('Char ' . $digit . ' is unsupported');
-            }
-            $seq .= $chr[$digit];
-        }
-        $seq .= '1101011';
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
-
-        return $this->binseq_to_array($seq, $bararray);
-    }
-
-    /**
-     * Convert binary barcode sequence to TCPDF barcode array.
-     *
-     * @param $seq (string) barcode as binary sequence.
-     * @param $bararray (array) barcode array.
-     * òparam array $bararray TCPDF barcode array to fill up
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function binseq_to_array($seq, $bararray)
-    {
-        $len = strlen($seq);
-        $w = 0;
-        $k = 0;
-        for ($i = 0; $i < $len; ++$i) {
-            $w += 1;
-            if (($i == ($len - 1)) OR (($i < ($len - 1)) AND ($seq{$i} != $seq{($i + 1)}))) {
-                if ($seq{$i} == '1') {
-                    $t = true; // bar
-                } else {
-                    $t = false; // space
-                }
-                $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
-                $bararray['maxw'] += $w;
-                ++$k;
-                $w = 0;
-            }
-        }
-
-        return $bararray;
-    }
-
-    /**
-     * Interleaved 2 of 5 barcodes.
-     * Compact numeric code, widely used in industry, air cargo
-     * Contains digits (0 to 9) and encodes the data in the width of both bars and spaces.
-     *
-     * @param $code (string) code to represent.
-     * @param $checksum (boolean) if true add a checksum to the code
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_i25($code, $checksum = false)
-    {
-        $chr['0'] = '11221';
-        $chr['1'] = '21112';
-        $chr['2'] = '12112';
-        $chr['3'] = '22111';
-        $chr['4'] = '11212';
-        $chr['5'] = '21211';
-        $chr['6'] = '12211';
-        $chr['7'] = '11122';
-        $chr['8'] = '21121';
-        $chr['9'] = '12121';
-        $chr['A'] = '11';
-        $chr['Z'] = '21';
-        if ($checksum) {
-            // add checksum
-            $code .= $this->checksum_s25($code);
-        }
-        if ((strlen($code) % 2) != 0) {
-            // add leading zero if code-length is odd
-            $code = '0' . $code;
-        }
-        // add start and stop codes
-        $code = 'AA' . strtolower($code) . 'ZA';
-
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
-        $k = 0;
-        $clen = strlen($code);
-        for ($i = 0; $i < $clen; $i = ($i + 2)) {
-            $char_bar = $code{$i};
-            $char_space = $code{$i + 1};
-            if ( ! isset($chr[$char_bar]) || ! isset($chr[$char_space])) {
-                throw new InvalidCharacterException();
-            }
-            // create a bar-space sequence
-            $seq = '';
-            $chrlen = strlen($chr[$char_bar]);
-            for ($s = 0; $s < $chrlen; $s++) {
-                $seq .= $chr[$char_bar]{$s} . $chr[$char_space]{$s};
-            }
-            $seqlen = strlen($seq);
-            for ($j = 0; $j < $seqlen; ++$j) {
-                if (($j % 2) == 0) {
-                    $t = true; // bar
-                } else {
-                    $t = false; // space
-                }
-                $w = $seq{$j};
-                $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
-                $bararray['maxw'] += $w;
-                ++$k;
-            }
-        }
-
-        return $bararray;
-    }
-
-    /**
-     * C128 barcodes.
-     * Very capable code, excellent density, high reliability; in very wide use world-wide
-     *
-     * @param $code (string) code to represent.
-     * @param $type (string) barcode type: A, B, C or empty for automatic switch (AUTO mode)
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_c128($code, $type = '')
-    {
-        $chr = array(
-            '212222', /* 00 */
-            '222122', /* 01 */
-            '222221', /* 02 */
-            '121223', /* 03 */
-            '121322', /* 04 */
-            '131222', /* 05 */
-            '122213', /* 06 */
-            '122312', /* 07 */
-            '132212', /* 08 */
-            '221213', /* 09 */
-            '221312', /* 10 */
-            '231212', /* 11 */
-            '112232', /* 12 */
-            '122132', /* 13 */
-            '122231', /* 14 */
-            '113222', /* 15 */
-            '123122', /* 16 */
-            '123221', /* 17 */
-            '223211', /* 18 */
-            '221132', /* 19 */
-            '221231', /* 20 */
-            '213212', /* 21 */
-            '223112', /* 22 */
-            '312131', /* 23 */
-            '311222', /* 24 */
-            '321122', /* 25 */
-            '321221', /* 26 */
-            '312212', /* 27 */
-            '322112', /* 28 */
-            '322211', /* 29 */
-            '212123', /* 30 */
-            '212321', /* 31 */
-            '232121', /* 32 */
-            '111323', /* 33 */
-            '131123', /* 34 */
-            '131321', /* 35 */
-            '112313', /* 36 */
-            '132113', /* 37 */
-            '132311', /* 38 */
-            '211313', /* 39 */
-            '231113', /* 40 */
-            '231311', /* 41 */
-            '112133', /* 42 */
-            '112331', /* 43 */
-            '132131', /* 44 */
-            '113123', /* 45 */
-            '113321', /* 46 */
-            '133121', /* 47 */
-            '313121', /* 48 */
-            '211331', /* 49 */
-            '231131', /* 50 */
-            '213113', /* 51 */
-            '213311', /* 52 */
-            '213131', /* 53 */
-            '311123', /* 54 */
-            '311321', /* 55 */
-            '331121', /* 56 */
-            '312113', /* 57 */
-            '312311', /* 58 */
-            '332111', /* 59 */
-            '314111', /* 60 */
-            '221411', /* 61 */
-            '431111', /* 62 */
-            '111224', /* 63 */
-            '111422', /* 64 */
-            '121124', /* 65 */
-            '121421', /* 66 */
-            '141122', /* 67 */
-            '141221', /* 68 */
-            '112214', /* 69 */
-            '112412', /* 70 */
-            '122114', /* 71 */
-            '122411', /* 72 */
-            '142112', /* 73 */
-            '142211', /* 74 */
-            '241211', /* 75 */
-            '221114', /* 76 */
-            '413111', /* 77 */
-            '241112', /* 78 */
-            '134111', /* 79 */
-            '111242', /* 80 */
-            '121142', /* 81 */
-            '121241', /* 82 */
-            '114212', /* 83 */
-            '124112', /* 84 */
-            '124211', /* 85 */
-            '411212', /* 86 */
-            '421112', /* 87 */
-            '421211', /* 88 */
-            '212141', /* 89 */
-            '214121', /* 90 */
-            '412121', /* 91 */
-            '111143', /* 92 */
-            '111341', /* 93 */
-            '131141', /* 94 */
-            '114113', /* 95 */
-            '114311', /* 96 */
-            '411113', /* 97 */
-            '411311', /* 98 */
-            '113141', /* 99 */
-            '114131', /* 100 */
-            '311141', /* 101 */
-            '411131', /* 102 */
-            '211412', /* 103 START A */
-            '211214', /* 104 START B */
-            '211232', /* 105 START C */
-            '233111', /* STOP */
-            '200000'  /* END */
-        );
-        // ASCII characters for code A (ASCII 00 - 95)
-        $keys_a = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_';
-        $keys_a .= chr(0) . chr(1) . chr(2) . chr(3) . chr(4) . chr(5) . chr(6) . chr(7) . chr(8) . chr(9);
-        $keys_a .= chr(10) . chr(11) . chr(12) . chr(13) . chr(14) . chr(15) . chr(16) . chr(17) . chr(18) . chr(19);
-        $keys_a .= chr(20) . chr(21) . chr(22) . chr(23) . chr(24) . chr(25) . chr(26) . chr(27) . chr(28) . chr(29);
-        $keys_a .= chr(30) . chr(31);
-        // ASCII characters for code B (ASCII 32 - 127)
-        $keys_b = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~' . chr(127);
-        // special codes
-        $fnc_a = array(241 => 102, 242 => 97, 243 => 96, 244 => 101);
-        $fnc_b = array(241 => 102, 242 => 97, 243 => 96, 244 => 100);
-        // array of symbols
-        $code_data = array();
-        // length of the code
-        $len = strlen($code);
-        switch (strtoupper($type)) {
-            case 'A': { // MODE A
-                $startid = 103;
-                for ($i = 0; $i < $len; ++$i) {
-                    $char = $code{$i};
-                    $char_id = ord($char);
-                    if (($char_id >= 241) AND ($char_id <= 244)) {
-                        $code_data[] = $fnc_a[$char_id];
-                    } elseif (($char_id >= 0) AND ($char_id <= 95)) {
-                        $code_data[] = strpos($keys_a, $char);
-                    } else {
-                        throw new InvalidCharacterException('Char ' . $char . ' is unsupported');
-                    }
-                }
-                break;
-            }
-            case 'B': { // MODE B
-                $startid = 104;
-                for ($i = 0; $i < $len; ++$i) {
-                    $char = $code{$i};
-                    $char_id = ord($char);
-                    if (($char_id >= 241) AND ($char_id <= 244)) {
-                        $code_data[] = $fnc_b[$char_id];
-                    } elseif (($char_id >= 32) AND ($char_id <= 127)) {
-                        $code_data[] = strpos($keys_b, $char);
-                    } else {
-                        throw new InvalidCharacterException('Char ' . $char . ' is unsupported');
-                    }
-                }
-                break;
-            }
-            case 'C': { // MODE C
-                $startid = 105;
-                if (ord($code[0]) == 241) {
-                    $code_data[] = 102;
-                    $code = substr($code, 1);
-                    --$len;
-                }
-                if (($len % 2) != 0) {
-                    throw new InvalidLengthException('Length must be even');
-                }
-                for ($i = 0; $i < $len; $i += 2) {
-                    $chrnum = $code{$i} . $code{$i + 1};
-                    if (preg_match('/([0-9]{2})/', $chrnum) > 0) {
-                        $code_data[] = intval($chrnum);
-                    } else {
-                        throw new InvalidCharacterException();
-                    }
-                }
-                break;
-            }
-            default: { // MODE AUTO
-                // split code into sequences
-                $sequence = array();
-                // get numeric sequences (if any)
-                $numseq = array();
-                preg_match_all('/([0-9]{4,})/', $code, $numseq, PREG_OFFSET_CAPTURE);
-                if (isset($numseq[1]) AND ! empty($numseq[1])) {
-                    $end_offset = 0;
-                    foreach ($numseq[1] as $val) {
-                        $offset = $val[1];
-                        if ($offset > $end_offset) {
-                            // non numeric sequence
-                            $sequence = array_merge($sequence,
-                                $this->get128ABsequence(substr($code, $end_offset, ($offset - $end_offset))));
-                        }
-                        // numeric sequence
-                        $slen = strlen($val[0]);
-                        if (($slen % 2) != 0) {
-                            // the length must be even
-                            --$slen;
-                        }
-                        $sequence[] = array('C', substr($code, $offset, $slen), $slen);
-                        $end_offset = $offset + $slen;
-                    }
-                    if ($end_offset < $len) {
-                        $sequence = array_merge($sequence, $this->get128ABsequence(substr($code, $end_offset)));
-                    }
-                } else {
-                    // text code (non C mode)
-                    $sequence = array_merge($sequence, $this->get128ABsequence($code));
-                }
-                // process the sequence
-                foreach ($sequence as $key => $seq) {
-                    switch ($seq[0]) {
-                        case 'A': {
-                            if ($key == 0) {
-                                $startid = 103;
-                            } elseif ($sequence[($key - 1)][0] != 'A') {
-                                if (($seq[2] == 1) AND ($key > 0) AND ($sequence[($key - 1)][0] == 'B') AND ( ! isset($sequence[($key - 1)][3]))) {
-                                    // single character shift
-                                    $code_data[] = 98;
-                                    // mark shift
-                                    $sequence[$key][3] = true;
-                                } elseif ( ! isset($sequence[($key - 1)][3])) {
-                                    $code_data[] = 101;
-                                }
-                            }
-                            for ($i = 0; $i < $seq[2]; ++$i) {
-                                $char = $seq[1]{$i};
-                                $char_id = ord($char);
-                                if (($char_id >= 241) AND ($char_id <= 244)) {
-                                    $code_data[] = $fnc_a[$char_id];
-                                } else {
-                                    $code_data[] = strpos($keys_a, $char);
-                                }
-                            }
-                            break;
-                        }
-                        case 'B': {
-                            if ($key == 0) {
-                                $tmpchr = ord($seq[1][0]);
-                                if (($seq[2] == 1) AND ($tmpchr >= 241) AND ($tmpchr <= 244) AND isset($sequence[($key + 1)]) AND ($sequence[($key + 1)][0] != 'B')) {
-                                    switch ($sequence[($key + 1)][0]) {
-                                        case 'A': {
-                                            $startid = 103;
-                                            $sequence[$key][0] = 'A';
-                                            $code_data[] = $fnc_a[$tmpchr];
-                                            break;
-                                        }
-                                        case 'C': {
-                                            $startid = 105;
-                                            $sequence[$key][0] = 'C';
-                                            $code_data[] = $fnc_a[$tmpchr];
-                                            break;
-                                        }
-                                    }
-                                    break;
-                                } else {
-                                    $startid = 104;
-                                }
-                            } elseif ($sequence[($key - 1)][0] != 'B') {
-                                if (($seq[2] == 1) AND ($key > 0) AND ($sequence[($key - 1)][0] == 'A') AND ( ! isset($sequence[($key - 1)][3]))) {
-                                    // single character shift
-                                    $code_data[] = 98;
-                                    // mark shift
-                                    $sequence[$key][3] = true;
-                                } elseif ( ! isset($sequence[($key - 1)][3])) {
-                                    $code_data[] = 100;
-                                }
-                            }
-                            for ($i = 0; $i < $seq[2]; ++$i) {
-                                $char = $seq[1]{$i};
-                                $char_id = ord($char);
-                                if (($char_id >= 241) AND ($char_id <= 244)) {
-                                    $code_data[] = $fnc_b[$char_id];
-                                } else {
-                                    $code_data[] = strpos($keys_b, $char);
-                                }
-                            }
-                            break;
-                        }
-                        case 'C': {
-                            if ($key == 0) {
-                                $startid = 105;
-                            } elseif ($sequence[($key - 1)][0] != 'C') {
-                                $code_data[] = 99;
-                            }
-                            for ($i = 0; $i < $seq[2]; $i += 2) {
-                                $chrnum = $seq[1]{$i} . $seq[1]{$i + 1};
-                                $code_data[] = intval($chrnum);
-                            }
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-        // calculate check character
-        $sum = $startid;
-        foreach ($code_data as $key => $val) {
-            $sum += ($val * ($key + 1));
-        }
-        // add check character
-        $code_data[] = ($sum % 103);
-        // add stop sequence
-        $code_data[] = 106;
-        $code_data[] = 107;
-        // add start code at the beginning
-        array_unshift($code_data, $startid);
-        // build barcode array
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
-        foreach ($code_data as $val) {
-            $seq = $chr[$val];
-            for ($j = 0; $j < 6; ++$j) {
-                if (($j % 2) == 0) {
-                    $t = true; // bar
-                } else {
-                    $t = false; // space
-                }
-                $w = $seq{$j};
-                $bararray['bcode'][] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
-                $bararray['maxw'] += $w;
-            }
-        }
-
-        return $bararray;
-    }
-
-    /**
-     * Split text code in A/B sequence for 128 code
-     *
-     * @param $code (string) code to split.
-     * @return array sequence
-     * @protected
-     */
-    protected function get128ABsequence($code)
-    {
-        $len = strlen($code);
-        $sequence = array();
-        // get A sequences (if any)
-        $numseq = array();
-        preg_match_all('/([\x00-\x1f])/', $code, $numseq, PREG_OFFSET_CAPTURE);
-        if (isset($numseq[1]) AND ! empty($numseq[1])) {
-            $end_offset = 0;
-            foreach ($numseq[1] as $val) {
-                $offset = $val[1];
-                if ($offset > $end_offset) {
-                    // B sequence
-                    $sequence[] = array(
-                        'B',
-                        substr($code, $end_offset, ($offset - $end_offset)),
-                        ($offset - $end_offset)
-                    );
-                }
-                // A sequence
-                $slen = strlen($val[0]);
-                $sequence[] = array('A', substr($code, $offset, $slen), $slen);
-                $end_offset = $offset + $slen;
-            }
-            if ($end_offset < $len) {
-                $sequence[] = array('B', substr($code, $end_offset), ($len - $end_offset));
-            }
-        } else {
-            // only B sequence
-            $sequence[] = array('B', $code, $len);
-        }
-
-        return $sequence;
-    }
-
-    /**
-     * EAN13 and UPC-A barcodes.
-     * EAN13: European Article Numbering international retail product code
-     * UPC-A: Universal product code seen on almost all retail products in the USA and Canada
-     * UPC-E: Short version of UPC symbol
-     *
-     * @param $code (string) code to represent.
-     * @param $len (string) barcode type: 6 = UPC-E, 8 = EAN8, 13 = EAN13, 12 = UPC-A
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_eanupc($code, $len = 13)
-    {
-        $upce = false;
-        if ($len == 6) {
-            $len = 12; // UPC-A
-            $upce = true; // UPC-E mode
-        }
-        $data_len = $len - 1;
-        //Padding
-        $code = str_pad($code, $data_len, '0', STR_PAD_LEFT);
-        $code_len = strlen($code);
-        // calculate check digit
-        $sum_a = 0;
-        for ($i = 1; $i < $data_len; $i += 2) {
-            $sum_a += $code{$i};
-        }
-        if ($len > 12) {
-            $sum_a *= 3;
-        }
-        $sum_b = 0;
-        for ($i = 0; $i < $data_len; $i += 2) {
-            $sum_b += ($code{$i});
-        }
-        if ($len < 13) {
-            $sum_b *= 3;
-        }
-        $r = ($sum_a + $sum_b) % 10;
-        if ($r > 0) {
-            $r = (10 - $r);
-        }
-        if ($code_len == $data_len) {
-            // add check digit
-            $code .= $r;
-        } elseif ($r !== intval($code{$data_len})) {
-            throw new InvalidCheckDigitException();
-        }
-        if ($len == 12) {
-            // UPC-A
-            $code = '0' . $code;
-            ++$len;
-        }
-        if ($upce) {
-            // convert UPC-A to UPC-E
-            $tmp = substr($code, 4, 3);
-            if (($tmp == '000') OR ($tmp == '100') OR ($tmp == '200')) {
-                // manufacturer code ends in 000, 100, or 200
-                $upce_code = substr($code, 2, 2) . substr($code, 9, 3) . substr($code, 4, 1);
-            } else {
-                $tmp = substr($code, 5, 2);
-                if ($tmp == '00') {
-                    // manufacturer code ends in 00
-                    $upce_code = substr($code, 2, 3) . substr($code, 10, 2) . '3';
-                } else {
-                    $tmp = substr($code, 6, 1);
-                    if ($tmp == '0') {
-                        // manufacturer code ends in 0
-                        $upce_code = substr($code, 2, 4) . substr($code, 11, 1) . '4';
-                    } else {
-                        // manufacturer code does not end in zero
-                        $upce_code = substr($code, 2, 5) . substr($code, 11, 1);
-                    }
-                }
-            }
-        }
-        //Convert digits to bars
-        $codes = array(
-            'A' => array( // left odd parity
-                '0' => '0001101',
-                '1' => '0011001',
-                '2' => '0010011',
-                '3' => '0111101',
-                '4' => '0100011',
-                '5' => '0110001',
-                '6' => '0101111',
-                '7' => '0111011',
-                '8' => '0110111',
-                '9' => '0001011'
-            ),
-            'B' => array( // left even parity
-                '0' => '0100111',
-                '1' => '0110011',
-                '2' => '0011011',
-                '3' => '0100001',
-                '4' => '0011101',
-                '5' => '0111001',
-                '6' => '0000101',
-                '7' => '0010001',
-                '8' => '0001001',
-                '9' => '0010111'
-            ),
-            'C' => array( // right
-                '0' => '1110010',
-                '1' => '1100110',
-                '2' => '1101100',
-                '3' => '1000010',
-                '4' => '1011100',
-                '5' => '1001110',
-                '6' => '1010000',
-                '7' => '1000100',
-                '8' => '1001000',
-                '9' => '1110100'
-            )
-        );
-        $parities = array(
-            '0' => array('A', 'A', 'A', 'A', 'A', 'A'),
-            '1' => array('A', 'A', 'B', 'A', 'B', 'B'),
-            '2' => array('A', 'A', 'B', 'B', 'A', 'B'),
-            '3' => array('A', 'A', 'B', 'B', 'B', 'A'),
-            '4' => array('A', 'B', 'A', 'A', 'B', 'B'),
-            '5' => array('A', 'B', 'B', 'A', 'A', 'B'),
-            '6' => array('A', 'B', 'B', 'B', 'A', 'A'),
-            '7' => array('A', 'B', 'A', 'B', 'A', 'B'),
-            '8' => array('A', 'B', 'A', 'B', 'B', 'A'),
-            '9' => array('A', 'B', 'B', 'A', 'B', 'A')
-        );
-        $upce_parities = array();
-        $upce_parities[0] = array(
-            '0' => array('B', 'B', 'B', 'A', 'A', 'A'),
-            '1' => array('B', 'B', 'A', 'B', 'A', 'A'),
-            '2' => array('B', 'B', 'A', 'A', 'B', 'A'),
-            '3' => array('B', 'B', 'A', 'A', 'A', 'B'),
-            '4' => array('B', 'A', 'B', 'B', 'A', 'A'),
-            '5' => array('B', 'A', 'A', 'B', 'B', 'A'),
-            '6' => array('B', 'A', 'A', 'A', 'B', 'B'),
-            '7' => array('B', 'A', 'B', 'A', 'B', 'A'),
-            '8' => array('B', 'A', 'B', 'A', 'A', 'B'),
-            '9' => array('B', 'A', 'A', 'B', 'A', 'B')
-        );
-        $upce_parities[1] = array(
-            '0' => array('A', 'A', 'A', 'B', 'B', 'B'),
-            '1' => array('A', 'A', 'B', 'A', 'B', 'B'),
-            '2' => array('A', 'A', 'B', 'B', 'A', 'B'),
-            '3' => array('A', 'A', 'B', 'B', 'B', 'A'),
-            '4' => array('A', 'B', 'A', 'A', 'B', 'B'),
-            '5' => array('A', 'B', 'B', 'A', 'A', 'B'),
-            '6' => array('A', 'B', 'B', 'B', 'A', 'A'),
-            '7' => array('A', 'B', 'A', 'B', 'A', 'B'),
-            '8' => array('A', 'B', 'A', 'B', 'B', 'A'),
-            '9' => array('A', 'B', 'B', 'A', 'B', 'A')
-        );
-        $k = 0;
-        $seq = '101'; // left guard bar
-        if ($upce) {
-            $bararray = array('code' => $upce_code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
-            $p = $upce_parities[$code[1]][$r];
-            for ($i = 0; $i < 6; ++$i) {
-                $seq .= $codes[$p[$i]][$upce_code{$i}];
-            }
-            $seq .= '010101'; // right guard bar
-        } else {
-            $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
-            $half_len = intval(ceil($len / 2));
-            if ($len == 8) {
-                for ($i = 0; $i < $half_len; ++$i) {
-                    $seq .= $codes['A'][$code{$i}];
-                }
-            } else {
-                $p = $parities[$code[0]];
-                for ($i = 1; $i < $half_len; ++$i) {
-                    $seq .= $codes[$p[$i - 1]][$code{$i}];
-                }
-            }
-            $seq .= '01010'; // center guard bar
-            for ($i = $half_len; $i < $len; ++$i) {
-                if ( ! isset($codes['C'][$code{$i}])) {
-                    throw new InvalidCharacterException('Char ' . $code{$i} . ' not allowed');
-                }
-                $seq .= $codes['C'][$code{$i}];
-            }
-            $seq .= '101'; // right guard bar
-        }
-        $clen = strlen($seq);
-        $w = 0;
-        for ($i = 0; $i < $clen; ++$i) {
-            $w += 1;
-            if (($i == ($clen - 1)) OR (($i < ($clen - 1)) AND ($seq{$i} != $seq{($i + 1)}))) {
-                if ($seq{$i} == '1') {
-                    $t = true; // bar
-                } else {
-                    $t = false; // space
-                }
-                $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
-                $bararray['maxw'] += $w;
-                ++$k;
-                $w = 0;
-            }
-        }
-
-        return $bararray;
-    }
-
-    /**
-     * UPC-Based Extensions
-     * 2-Digit Ext.: Used to indicate magazines and newspaper issue numbers
-     * 5-Digit Ext.: Used to mark suggested retail price of books
-     *
-     * @param $code (string) code to represent.
-     * @param $len (string) barcode type: 2 = 2-Digit, 5 = 5-Digit
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_eanext($code, $len = 5)
-    {
-        //Padding
-        $code = str_pad($code, $len, '0', STR_PAD_LEFT);
-        // calculate check digit
-        if ($len == 2) {
-            $r = $code % 4;
-        } elseif ($len == 5) {
-            $r = (3 * ($code[0] + $code[2] + $code[4])) + (9 * ($code[1] + $code[3]));
-            $r %= 10;
-        } else {
-            throw new InvalidCheckDigitException();
-        }
-        //Convert digits to bars
-        $codes = array(
-            'A' => array( // left odd parity
-                '0' => '0001101',
-                '1' => '0011001',
-                '2' => '0010011',
-                '3' => '0111101',
-                '4' => '0100011',
-                '5' => '0110001',
-                '6' => '0101111',
-                '7' => '0111011',
-                '8' => '0110111',
-                '9' => '0001011'
-            ),
-            'B' => array( // left even parity
-                '0' => '0100111',
-                '1' => '0110011',
-                '2' => '0011011',
-                '3' => '0100001',
-                '4' => '0011101',
-                '5' => '0111001',
-                '6' => '0000101',
-                '7' => '0010001',
-                '8' => '0001001',
-                '9' => '0010111'
-            )
-        );
-        $parities = array();
-        $parities[2] = array(
-            '0' => array('A', 'A'),
-            '1' => array('A', 'B'),
-            '2' => array('B', 'A'),
-            '3' => array('B', 'B')
-        );
-        $parities[5] = array(
-            '0' => array('B', 'B', 'A', 'A', 'A'),
-            '1' => array('B', 'A', 'B', 'A', 'A'),
-            '2' => array('B', 'A', 'A', 'B', 'A'),
-            '3' => array('B', 'A', 'A', 'A', 'B'),
-            '4' => array('A', 'B', 'B', 'A', 'A'),
-            '5' => array('A', 'A', 'B', 'B', 'A'),
-            '6' => array('A', 'A', 'A', 'B', 'B'),
-            '7' => array('A', 'B', 'A', 'B', 'A'),
-            '8' => array('A', 'B', 'A', 'A', 'B'),
-            '9' => array('A', 'A', 'B', 'A', 'B')
-        );
-        $p = $parities[$len][$r];
-        $seq = '1011'; // left guard bar
-        $seq .= $codes[$p[0]][$code[0]];
-        for ($i = 1; $i < $len; ++$i) {
-            $seq .= '01'; // separator
-            $seq .= $codes[$p[$i]][$code{$i}];
-        }
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
-
-        return $this->binseq_to_array($seq, $bararray);
-    }
-
-    /**
-     * POSTNET and PLANET barcodes.
-     * Used by U.S. Postal Service for automated mail sorting
-     *
-     * @param $code (string) zip code to represent. Must be a string containing a zip code of the form DDDDD or
-     *     DDDDD-DDDD.
-     * @param $planet (boolean) if true print the PLANET barcode, otherwise print POSTNET
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_postnet($code, $planet = false)
-    {
-        // bar length
-        if ($planet) {
-            $barlen = Array(
-                0 => Array(1, 1, 2, 2, 2),
-                1 => Array(2, 2, 2, 1, 1),
-                2 => Array(2, 2, 1, 2, 1),
-                3 => Array(2, 2, 1, 1, 2),
-                4 => Array(2, 1, 2, 2, 1),
-                5 => Array(2, 1, 2, 1, 2),
-                6 => Array(2, 1, 1, 2, 2),
-                7 => Array(1, 2, 2, 2, 1),
-                8 => Array(1, 2, 2, 1, 2),
-                9 => Array(1, 2, 1, 2, 2)
-            );
-        } else {
-            $barlen = Array(
-                0 => Array(2, 2, 1, 1, 1),
-                1 => Array(1, 1, 1, 2, 2),
-                2 => Array(1, 1, 2, 1, 2),
-                3 => Array(1, 1, 2, 2, 1),
-                4 => Array(1, 2, 1, 1, 2),
-                5 => Array(1, 2, 1, 2, 1),
-                6 => Array(1, 2, 2, 1, 1),
-                7 => Array(2, 1, 1, 1, 2),
-                8 => Array(2, 1, 1, 2, 1),
-                9 => Array(2, 1, 2, 1, 1)
-            );
-        }
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
-        $k = 0;
-        $code = str_replace('-', '', $code);
-        $code = str_replace(' ', '', $code);
-        $len = strlen($code);
-        // calculate checksum
-        $sum = 0;
-        for ($i = 0; $i < $len; ++$i) {
-            $sum += intval($code{$i});
-        }
-        $chkd = ($sum % 10);
-        if ($chkd > 0) {
-            $chkd = (10 - $chkd);
-        }
-        $code .= $chkd;
-        $len = strlen($code);
-        // start bar
-        $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
-        $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
-        $bararray['maxw'] += 2;
-        for ($i = 0; $i < $len; ++$i) {
-            for ($j = 0; $j < 5; ++$j) {
-                $h = $barlen[$code{$i}][$j];
-                $p = floor(1 / $h);
-                $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
-                $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
-                $bararray['maxw'] += 2;
-            }
-        }
-        // end bar
-        $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
-        $bararray['maxw'] += 1;
-
-        return $bararray;
-    }
-
-    /**
-     * RMS4CC - CBC - KIX
-     * RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) - KIX (Klant index - Customer index)
-     * RM4SCC is the name of the barcode symbology used by the Royal Mail for its Cleanmail service.
-     *
-     * @param $code (string) code to print
-     * @param $kix (boolean) if true prints the KIX variation (doesn't use the start and end symbols, and the checksum)
-     *     - in this case the house number must be sufficed with an X and placed at the end of the code.
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_rms4cc($code, $kix = false)
-    {
-        $notkix = ! $kix;
-        // bar mode
-        // 1 = pos 1, length 2
-        // 2 = pos 1, length 3
-        // 3 = pos 2, length 1
-        // 4 = pos 2, length 2
-        $barmode = array(
-            '0' => array(3, 3, 2, 2),
-            '1' => array(3, 4, 1, 2),
-            '2' => array(3, 4, 2, 1),
-            '3' => array(4, 3, 1, 2),
-            '4' => array(4, 3, 2, 1),
-            '5' => array(4, 4, 1, 1),
-            '6' => array(3, 1, 4, 2),
-            '7' => array(3, 2, 3, 2),
-            '8' => array(3, 2, 4, 1),
-            '9' => array(4, 1, 3, 2),
-            'A' => array(4, 1, 4, 1),
-            'B' => array(4, 2, 3, 1),
-            'C' => array(3, 1, 2, 4),
-            'D' => array(3, 2, 1, 4),
-            'E' => array(3, 2, 2, 3),
-            'F' => array(4, 1, 1, 4),
-            'G' => array(4, 1, 2, 3),
-            'H' => array(4, 2, 1, 3),
-            'I' => array(1, 3, 4, 2),
-            'J' => array(1, 4, 3, 2),
-            'K' => array(1, 4, 4, 1),
-            'L' => array(2, 3, 3, 2),
-            'M' => array(2, 3, 4, 1),
-            'N' => array(2, 4, 3, 1),
-            'O' => array(1, 3, 2, 4),
-            'P' => array(1, 4, 1, 4),
-            'Q' => array(1, 4, 2, 3),
-            'R' => array(2, 3, 1, 4),
-            'S' => array(2, 3, 2, 3),
-            'T' => array(2, 4, 1, 3),
-            'U' => array(1, 1, 4, 4),
-            'V' => array(1, 2, 3, 4),
-            'W' => array(1, 2, 4, 3),
-            'X' => array(2, 1, 3, 4),
-            'Y' => array(2, 1, 4, 3),
-            'Z' => array(2, 2, 3, 3)
-        );
-        $code = strtoupper($code);
-        $len = strlen($code);
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
-        if ($notkix) {
-            // table for checksum calculation (row,col)
-            $checktable = array(
-                '0' => array(1, 1),
-                '1' => array(1, 2),
-                '2' => array(1, 3),
-                '3' => array(1, 4),
-                '4' => array(1, 5),
-                '5' => array(1, 0),
-                '6' => array(2, 1),
-                '7' => array(2, 2),
-                '8' => array(2, 3),
-                '9' => array(2, 4),
-                'A' => array(2, 5),
-                'B' => array(2, 0),
-                'C' => array(3, 1),
-                'D' => array(3, 2),
-                'E' => array(3, 3),
-                'F' => array(3, 4),
-                'G' => array(3, 5),
-                'H' => array(3, 0),
-                'I' => array(4, 1),
-                'J' => array(4, 2),
-                'K' => array(4, 3),
-                'L' => array(4, 4),
-                'M' => array(4, 5),
-                'N' => array(4, 0),
-                'O' => array(5, 1),
-                'P' => array(5, 2),
-                'Q' => array(5, 3),
-                'R' => array(5, 4),
-                'S' => array(5, 5),
-                'T' => array(5, 0),
-                'U' => array(0, 1),
-                'V' => array(0, 2),
-                'W' => array(0, 3),
-                'X' => array(0, 4),
-                'Y' => array(0, 5),
-                'Z' => array(0, 0)
-            );
-            $row = 0;
-            $col = 0;
-            for ($i = 0; $i < $len; ++$i) {
-                $row += $checktable[$code{$i}][0];
-                $col += $checktable[$code{$i}][1];
-            }
-            $row %= 6;
-            $col %= 6;
-            $chk = array_keys($checktable, array($row, $col));
-            $code .= $chk[0];
-            ++$len;
-        }
-        $k = 0;
-        if ($notkix) {
-            // start bar
-            $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
-            $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
-            $bararray['maxw'] += 2;
-        }
-        for ($i = 0; $i < $len; ++$i) {
-            for ($j = 0; $j < 4; ++$j) {
-                switch ($barmode[$code{$i}][$j]) {
-                    case 1: {
-                        $p = 0;
-                        $h = 2;
-                        break;
-                    }
-                    case 2: {
-                        $p = 0;
-                        $h = 3;
-                        break;
-                    }
-                    case 3: {
-                        $p = 1;
-                        $h = 1;
-                        break;
-                    }
-                    case 4: {
-                        $p = 1;
-                        $h = 2;
-                        break;
-                    }
-                }
-                $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
-                $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
-                $bararray['maxw'] += 2;
-            }
-        }
-        if ($notkix) {
-            // stop bar
-            $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 3, 'p' => 0);
-            $bararray['maxw'] += 1;
-        }
-
-        return $bararray;
-    }
-
-    /**
-     * CODABAR barcodes.
-     * Older code often used in library systems, sometimes in blood banks
-     *
-     * @param $code (string) code to represent.
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_codabar($code)
-    {
-        $chr = array(
-            '0' => '11111221',
-            '1' => '11112211',
-            '2' => '11121121',
-            '3' => '22111111',
-            '4' => '11211211',
-            '5' => '21111211',
-            '6' => '12111121',
-            '7' => '12112111',
-            '8' => '12211111',
-            '9' => '21121111',
-            '-' => '11122111',
-            '$' => '11221111',
-            ':' => '21112121',
-            '/' => '21211121',
-            '.' => '21212111',
-            '+' => '11222221',
-            'A' => '11221211',
-            'B' => '12121121',
-            'C' => '11121221',
-            'D' => '11122211'
-        );
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
-        $k = 0;
-        $w = 0;
-        $seq = '';
-        $code = 'A' . strtoupper($code) . 'A';
-        $len = strlen($code);
-        for ($i = 0; $i < $len; ++$i) {
-            if ( ! isset($chr[$code{$i}])) {
-                throw new InvalidCharacterException('Char ' . $code{$i} . ' is unsupported');
-            }
-            $seq = $chr[$code{$i}];
-            for ($j = 0; $j < 8; ++$j) {
-                if (($j % 2) == 0) {
-                    $t = true; // bar
-                } else {
-                    $t = false; // space
-                }
-                $w = $seq{$j};
-                $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
-                $bararray['maxw'] += $w;
-                ++$k;
-            }
-        }
-
-        return $bararray;
-    }
-
-    /**
-     * CODE11 barcodes.
-     * Used primarily for labeling telecommunications equipment
-     *
-     * @param $code (string) code to represent.
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_code11($code)
-    {
-        $chr = array(
-            '0' => '111121',
-            '1' => '211121',
-            '2' => '121121',
-            '3' => '221111',
-            '4' => '112121',
-            '5' => '212111',
-            '6' => '122111',
-            '7' => '111221',
-            '8' => '211211',
-            '9' => '211111',
-            '-' => '112111',
-            'S' => '112211'
-        );
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
-        $k = 0;
-        $w = 0;
-        $seq = '';
-        $len = strlen($code);
-        // calculate check digit C
-        $p = 1;
-        $check = 0;
-        for ($i = ($len - 1); $i >= 0; --$i) {
-            $digit = $code{$i};
-            if ($digit == '-') {
-                $dval = 10;
-            } else {
-                $dval = intval($digit);
-            }
-            $check += ($dval * $p);
-            ++$p;
-            if ($p > 10) {
-                $p = 1;
-            }
-        }
-        $check %= 11;
-        if ($check == 10) {
-            $check = '-';
-        }
-        $code .= $check;
-        if ($len > 10) {
-            // calculate check digit K
-            $p = 1;
-            $check = 0;
-            for ($i = $len; $i >= 0; --$i) {
-                $digit = $code{$i};
-                if ($digit == '-') {
-                    $dval = 10;
-                } else {
-                    $dval = intval($digit);
-                }
-                $check += ($dval * $p);
-                ++$p;
-                if ($p > 9) {
-                    $p = 1;
-                }
-            }
-            $check %= 11;
-            $code .= $check;
-            ++$len;
-        }
-        $code = 'S' . $code . 'S';
-        $len += 3;
-        for ($i = 0; $i < $len; ++$i) {
-            if ( ! isset($chr[$code{$i}])) {
-                throw new InvalidCharacterException('Char ' . $code{$i} . ' is unsupported');
-            }
-            $seq = $chr[$code{$i}];
-            for ($j = 0; $j < 6; ++$j) {
-                if (($j % 2) == 0) {
-                    $t = true; // bar
-                } else {
-                    $t = false; // space
-                }
-                $w = $seq{$j};
-                $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
-                $bararray['maxw'] += $w;
-                ++$k;
-            }
-        }
-
-        return $bararray;
-    }
-
-    /**
-     * Pharmacode
-     * Contains digits (0 to 9)
-     *
-     * @param $code (string) code to represent.
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_pharmacode($code)
-    {
-        $seq = '';
-        $code = intval($code);
-        while ($code > 0) {
-            if (($code % 2) == 0) {
-                $seq .= '11100';
-                $code -= 2;
-            } else {
-                $seq .= '100';
-                $code -= 1;
-            }
-            $code /= 2;
-        }
-        $seq = substr($seq, 0, -2);
-        $seq = strrev($seq);
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
-
-        return $this->binseq_to_array($seq, $bararray);
-    }
-
-    /**
-     * Pharmacode two-track
-     * Contains digits (0 to 9)
-     *
-     * @param $code (string) code to represent.
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_pharmacode2t($code)
-    {
-        $seq = '';
-        $code = intval($code);
-        do {
-            switch ($code % 3) {
-                case 0: {
-                    $seq .= '3';
-                    $code = ($code - 3) / 3;
-                    break;
-                }
-                case 1: {
-                    $seq .= '1';
-                    $code = ($code - 1) / 3;
-                    break;
-                }
-                case 2: {
-                    $seq .= '2';
-                    $code = ($code - 2) / 3;
-                    break;
-                }
-            }
-        } while ($code != 0);
-        $seq = strrev($seq);
-        $k = 0;
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
-        $len = strlen($seq);
-        for ($i = 0; $i < $len; ++$i) {
-            switch ($seq{$i}) {
-                case '1': {
-                    $p = 1;
-                    $h = 1;
-                    break;
-                }
-                case '2': {
-                    $p = 0;
-                    $h = 1;
-                    break;
-                }
-                case '3': {
-                    $p = 0;
-                    $h = 2;
-                    break;
-                }
-            }
-            $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
-            $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
-            $bararray['maxw'] += 2;
-        }
-        unset($bararray['bcode'][($k - 1)]);
-        --$bararray['maxw'];
-
-        return $bararray;
-    }
-
-    /**
-     * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
-     * (requires PHP bcmath extension)
-     * Intelligent Mail barcode is a 65-bar code for use on mail in the United States.
-     * The fields are described as follows:<ul><li>The Barcode Identifier shall be assigned by USPS to encode the
-     * presort identification that is currently printed in human readable form on the optional endorsement line (OEL)
-     * as well as for future USPS use. This shall be two digits, with the second digit in the range of 0–4. The
-     * allowable encoding ranges shall be 00–04, 10–14, 20–24, 30–34, 40–44, 50–54, 60–64, 70–74, 80–84, and
-     * 90–94.</li><li>The Service Type Identifier shall be assigned by USPS for any combination of services requested
-     * on the mailpiece. The allowable encoding range shall be 000http://it2.php.net/manual/en/function.dechex.php–999.
-     * Each 3-digit value shall correspond to a particular mail class with a particular combination of service(s). Each
-     * service program, such as OneCode Confirm and OneCode ACS, shall provide the list of Service Type Identifier
-     * values.</li><li>The Mailer or Customer Identifier shall be assigned by USPS as a unique, 6 or 9 digit number
-     * that identifies a business entity. The allowable encoding range for the 6 digit Mailer ID shall be 000000-
-     * 899999, while the allowable encoding range for the 9 digit Mailer ID shall be 900000000-999999999.</li><li>The
-     * Serial or Sequence Number shall be assigned by the mailer for uniquely identifying and tracking mailpieces. The
-     * allowable encoding range shall be 000000000–999999999 when used with a 6 digit Mailer ID and 000000-999999 when
-     * used with a 9 digit Mailer ID. e. The Delivery Point ZIP Code shall be assigned by the mailer for routing the
-     * mailpiece. This shall replace POSTNET for routing the mailpiece to its final delivery point. The length may be
-     * 0, 5, 9, or 11 digits. The allowable encoding ranges shall be no ZIP Code, 00000–99999,  000000000–999999999,
-     * and 00000000000–99999999999.</li></ul>
-     *
-     * @param $code (string) code to print, separate the ZIP (routing code) from the rest using a minus char '-'
-     *     (BarcodeID_ServiceTypeID_MailerID_SerialNumber-RoutingCode)
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_imb($code)
-    {
-        $asc_chr = array(
-            4,
-            0,
-            2,
-            6,
-            3,
-            5,
-            1,
-            9,
-            8,
-            7,
-            1,
-            2,
-            0,
-            6,
-            4,
-            8,
-            2,
-            9,
-            5,
-            3,
-            0,
-            1,
-            3,
-            7,
-            4,
-            6,
-            8,
-            9,
-            2,
-            0,
-            5,
-            1,
-            9,
-            4,
-            3,
-            8,
-            6,
-            7,
-            1,
-            2,
-            4,
-            3,
-            9,
-            5,
-            7,
-            8,
-            3,
-            0,
-            2,
-            1,
-            4,
-            0,
-            9,
-            1,
-            7,
-            0,
-            2,
-            4,
-            6,
-            3,
-            7,
-            1,
-            9,
-            5,
-            8
-        );
-        $dsc_chr = array(
-            7,
-            1,
-            9,
-            5,
-            8,
-            0,
-            2,
-            4,
-            6,
-            3,
-            5,
-            8,
-            9,
-            7,
-            3,
-            0,
-            6,
-            1,
-            7,
-            4,
-            6,
-            8,
-            9,
-            2,
-            5,
-            1,
-            7,
-            5,
-            4,
-            3,
-            8,
-            7,
-            6,
-            0,
-            2,
-            5,
-            4,
-            9,
-            3,
-            0,
-            1,
-            6,
-            8,
-            2,
-            0,
-            4,
-            5,
-            9,
-            6,
-            7,
-            5,
-            2,
-            6,
-            3,
-            8,
-            5,
-            1,
-            9,
-            8,
-            7,
-            4,
-            0,
-            2,
-            6,
-            3
-        );
-        $asc_pos = array(
-            3,
-            0,
-            8,
-            11,
-            1,
-            12,
-            8,
-            11,
-            10,
-            6,
-            4,
-            12,
-            2,
-            7,
-            9,
-            6,
-            7,
-            9,
-            2,
-            8,
-            4,
-            0,
-            12,
-            7,
-            10,
-            9,
-            0,
-            7,
-            10,
-            5,
-            7,
-            9,
-            6,
-            8,
-            2,
-            12,
-            1,
-            4,
-            2,
-            0,
-            1,
-            5,
-            4,
-            6,
-            12,
-            1,
-            0,
-            9,
-            4,
-            7,
-            5,
-            10,
-            2,
-            6,
-            9,
-            11,
-            2,
-            12,
-            6,
-            7,
-            5,
-            11,
-            0,
-            3,
-            2
-        );
-        $dsc_pos = array(
-            2,
-            10,
-            12,
-            5,
-            9,
-            1,
-            5,
-            4,
-            3,
-            9,
-            11,
-            5,
-            10,
-            1,
-            6,
-            3,
-            4,
-            1,
-            10,
-            0,
-            2,
-            11,
-            8,
-            6,
-            1,
-            12,
-            3,
-            8,
-            6,
-            4,
-            4,
-            11,
-            0,
-            6,
-            1,
-            9,
-            11,
-            5,
-            3,
-            7,
-            3,
-            10,
-            7,
-            11,
-            8,
-            2,
-            10,
-            3,
-            5,
-            8,
-            0,
-            3,
-            12,
-            11,
-            8,
-            4,
-            5,
-            1,
-            3,
-            0,
-            7,
-            12,
-            9,
-            8,
-            10
-        );
-        $code_arr = explode('-', $code);
-        $tracking_number = $code_arr[0];
-        if (isset($code_arr[1])) {
-            $routing_code = $code_arr[1];
-        } else {
-            $routing_code = '';
-        }
-        // Conversion of Routing Code
-        switch (strlen($routing_code)) {
-            case 0: {
-                $binary_code = 0;
-                break;
-            }
-            case 5: {
-                $binary_code = bcadd($routing_code, '1');
-                break;
-            }
-            case 9: {
-                $binary_code = bcadd($routing_code, '100001');
-                break;
-            }
-            case 11: {
-                $binary_code = bcadd($routing_code, '1000100001');
-                break;
-            }
-            default: {
-                throw new BarcodeException('Routing code unknown');
-                break;
-            }
-        }
-        $binary_code = bcmul($binary_code, 10);
-        $binary_code = bcadd($binary_code, $tracking_number[0]);
-        $binary_code = bcmul($binary_code, 5);
-        $binary_code = bcadd($binary_code, $tracking_number[1]);
-        $binary_code .= substr($tracking_number, 2, 18);
-        // convert to hexadecimal
-        $binary_code = $this->dec_to_hex($binary_code);
-        // pad to get 13 bytes
-        $binary_code = str_pad($binary_code, 26, '0', STR_PAD_LEFT);
-        // convert string to array of bytes
-        $binary_code_arr = chunk_split($binary_code, 2, "\r");
-        $binary_code_arr = substr($binary_code_arr, 0, -1);
-        $binary_code_arr = explode("\r", $binary_code_arr);
-        // calculate frame check sequence
-        $fcs = $this->imb_crc11fcs($binary_code_arr);
-        // exclude first 2 bits from first byte
-        $first_byte = sprintf('%2s', dechex((hexdec($binary_code_arr[0]) << 2) >> 2));
-        $binary_code_102bit = $first_byte . substr($binary_code, 2);
-        // convert binary data to codewords
-        $codewords = array();
-        $data = $this->hex_to_dec($binary_code_102bit);
-        $codewords[0] = bcmod($data, 636) * 2;
-        $data = bcdiv($data, 636);
-        for ($i = 1; $i < 9; ++$i) {
-            $codewords[$i] = bcmod($data, 1365);
-            $data = bcdiv($data, 1365);
-        }
-        $codewords[9] = $data;
-        if (($fcs >> 10) == 1) {
-            $codewords[9] += 659;
-        }
-        // generate lookup tables
-        $table2of13 = $this->imb_tables(2, 78);
-        $table5of13 = $this->imb_tables(5, 1287);
-        // convert codewords to characters
-        $characters = array();
-        $bitmask = 512;
-        foreach ($codewords as $k => $val) {
-            if ($val <= 1286) {
-                $chrcode = $table5of13[$val];
-            } else {
-                $chrcode = $table2of13[($val - 1287)];
-            }
-            if (($fcs & $bitmask) > 0) {
-                // bitwise invert
-                $chrcode = ((~$chrcode) & 8191);
-            }
-            $characters[] = $chrcode;
-            $bitmask /= 2;
-        }
-        $characters = array_reverse($characters);
-        // build bars
-        $k = 0;
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
-        for ($i = 0; $i < 65; ++$i) {
-            $asc = (($characters[$asc_chr[$i]] & pow(2, $asc_pos[$i])) > 0);
-            $dsc = (($characters[$dsc_chr[$i]] & pow(2, $dsc_pos[$i])) > 0);
-            if ($asc AND $dsc) {
-                // full bar (F)
-                $p = 0;
-                $h = 3;
-            } elseif ($asc) {
-                // ascender (A)
-                $p = 0;
-                $h = 2;
-            } elseif ($dsc) {
-                // descender (D)
-                $p = 1;
-                $h = 2;
-            } else {
-                // tracker (T)
-                $p = 1;
-                $h = 1;
-            }
-            $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
-            $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
-            $bararray['maxw'] += 2;
-        }
-        unset($bararray['bcode'][($k - 1)]);
-        --$bararray['maxw'];
-
-        return $bararray;
-    }
-
-    /**
-     * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
-     *
-     * @param $code (string) pre-formatted IMB barcode (65 chars "FADT")
-     * @return array barcode representation.
-     * @protected
-     */
-    protected function barcode_imb_pre($code)
-    {
-        if ( ! preg_match('/^[fadtFADT]{65}$/', $code) == 1) {
-            throw new InvalidFormatException();
-        }
-        $characters = str_split(strtolower($code), 1);
-        // build bars
-        $k = 0;
-        $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
-        for ($i = 0; $i < 65; ++$i) {
-            switch ($characters[$i]) {
-                case 'f': {
-                    // full bar
-                    $p = 0;
-                    $h = 3;
-                    break;
-                }
-                case 'a': {
-                    // ascender
-                    $p = 0;
-                    $h = 2;
-                    break;
-                }
-                case 'd': {
-                    // descender
-                    $p = 1;
-                    $h = 2;
-                    break;
-                }
-                case 't': {
-                    // tracker (short)
-                    $p = 1;
-                    $h = 1;
-                    break;
-                }
-            }
-            $bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
-            $bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
-            $bararray['maxw'] += 2;
-        }
-        unset($bararray['bcode'][($k - 1)]);
-        --$bararray['maxw'];
-
-        return $bararray;
-    }
-
-    /**
-     * Convert large integer number to hexadecimal representation.
-     * (requires PHP bcmath extension)
-     *
-     * @param $number (string) number to convert specified as a string
-     * @return string hexadecimal representation
-     */
-    protected function dec_to_hex($number)
-    {
-        if ($number == 0) {
-            return '00';
-        }
-
-        $hex = [];
-
-        while ($number > 0) {
-            array_push($hex, strtoupper(dechex(bcmod($number, '16'))));
-            $number = bcdiv($number, '16', 0);
-        }
-        $hex = array_reverse($hex);
-
-        return implode($hex);
-    }
-
-    /**
-     * Convert large hexadecimal number to decimal representation (string).
-     * (requires PHP bcmath extension)
-     *
-     * @param $hex (string) hexadecimal number to convert specified as a string
-     * @return string hexadecimal representation
-     */
-    protected function hex_to_dec($hex)
-    {
-        $dec = 0;
-        $bitval = 1;
-        $len = strlen($hex);
-        for ($pos = ($len - 1); $pos >= 0; --$pos) {
-            $dec = bcadd($dec, bcmul(hexdec($hex{$pos}), $bitval));
-            $bitval = bcmul($bitval, 16);
-        }
-
-        return $dec;
-    }
-
-    /**
-     * Intelligent Mail Barcode calculation of Frame Check Sequence
-     *
-     * @param $code_arr (string) array of hexadecimal values (13 bytes holding 102 bits right justified).
-     * @return int 11 bit Frame Check Sequence as integer (decimal base)
-     * @protected
-     */
-    protected function imb_crc11fcs($code_arr)
-    {
-        $genpoly = 0x0F35; // generator polynomial
-        $fcs = 0x07FF; // Frame Check Sequence
-        // do most significant byte skipping the 2 most significant bits
-        $data = hexdec($code_arr[0]) << 5;
-        for ($bit = 2; $bit < 8; ++$bit) {
-            if (($fcs ^ $data) & 0x400) {
-                $fcs = ($fcs << 1) ^ $genpoly;
-            } else {
-                $fcs = ($fcs << 1);
-            }
-            $fcs &= 0x7FF;
-            $data <<= 1;
-        }
-        // do rest of bytes
-        for ($byte = 1; $byte < 13; ++$byte) {
-            $data = hexdec($code_arr[$byte]) << 3;
-            for ($bit = 0; $bit < 8; ++$bit) {
-                if (($fcs ^ $data) & 0x400) {
-                    $fcs = ($fcs << 1) ^ $genpoly;
-                } else {
-                    $fcs = ($fcs << 1);
-                }
-                $fcs &= 0x7FF;
-                $data <<= 1;
-            }
-        }
-
-        return $fcs;
-    }
-
-    /**
-     * Reverse unsigned short value
-     *
-     * @param $num (int) value to reversr
-     * @return int reversed value
-     * @protected
-     */
-    protected function imb_reverse_us($num)
-    {
-        $rev = 0;
-        for ($i = 0; $i < 16; ++$i) {
-            $rev <<= 1;
-            $rev |= ($num & 1);
-            $num >>= 1;
-        }
-
-        return $rev;
-    }
-
-    /**
-     * generate Nof13 tables used for Intelligent Mail Barcode
-     *
-     * @param $n (int) is the type of table: 2 for 2of13 table, 5 for 5of13table
-     * @param $size (int) size of table (78 for n=2 and 1287 for n=5)
-     * @return array requested table
-     * @protected
-     */
-    protected function imb_tables($n, $size)
-    {
-        $table = array();
-        $lli = 0; // LUT lower index
-        $lui = $size - 1; // LUT upper index
-        for ($count = 0; $count < 8192; ++$count) {
-            $bit_count = 0;
-            for ($bit_index = 0; $bit_index < 13; ++$bit_index) {
-                $bit_count += intval(($count & (1 << $bit_index)) != 0);
-            }
-            // if we don't have the right number of bits on, go on to the next value
-            if ($bit_count == $n) {
-                $reverse = ($this->imb_reverse_us($count) >> 3);
-                // if the reverse is less than count, we have already visited this pair before
-                if ($reverse >= $count) {
-                    // If count is symmetric, place it at the first free slot from the end of the list.
-                    // Otherwise, place it at the first free slot from the beginning of the list AND place $reverse ath the next free slot from the beginning of the list
-                    if ($reverse == $count) {
-                        $table[$lui] = $count;
-                        --$lui;
-                    } else {
-                        $table[$lli] = $count;
-                        ++$lli;
-                        $table[$lli] = $reverse;
-                        ++$lli;
-                    }
-                }
-            }
-        }
-
-        return $table;
-    }
-
-    protected function convertBarcodeArrayToNewStyle($oldBarcodeArray)
-    {
-        $newBarcodeArray = [];
-        $newBarcodeArray['code'] = $oldBarcodeArray['code'];
-        $newBarcodeArray['maxWidth'] = $oldBarcodeArray['maxw'];
-        $newBarcodeArray['maxHeight'] = $oldBarcodeArray['maxh'];
-        $newBarcodeArray['bars'] = [];
-        foreach ($oldBarcodeArray['bcode'] as $oldbar) {
-            $newBar = [];
-            $newBar['width'] = $oldbar['w'];
-            $newBar['height'] = $oldbar['h'];
-            $newBar['positionVertical'] = $oldbar['p'];
-            $newBar['drawBar'] = $oldbar['t'];
-            $newBar['drawSpacing'] = ! $oldbar['t'];
-
-            $newBarcodeArray['bars'][] = $newBar;
-        }
-
-        return $newBarcodeArray;
-    }
+	const TYPE_CODE_39 = 'C39';
+	const TYPE_CODE_39_CHECKSUM = 'C39+';
+	const TYPE_CODE_39E = 'C39E';
+	const TYPE_CODE_39E_CHECKSUM = 'C39E+';
+	const TYPE_CODE_93 = 'C93';
+	const TYPE_STANDARD_2_5 = 'S25';
+	const TYPE_STANDARD_2_5_CHECKSUM = 'S25+';
+	const TYPE_INTERLEAVED_2_5 = 'I25';
+	const TYPE_INTERLEAVED_2_5_CHECKSUM = 'I25+';
+	const TYPE_CODE_128 = 'C128';
+	const TYPE_CODE_128_A = 'C128A';
+	const TYPE_CODE_128_B = 'C128B';
+	const TYPE_CODE_128_C = 'C128C';
+	const TYPE_EAN_2 = 'EAN2';
+	const TYPE_EAN_5 = 'EAN5';
+	const TYPE_EAN_8 = 'EAN8';
+	const TYPE_EAN_13 = 'EAN13';
+	const TYPE_UPC_A = 'UPCA';
+	const TYPE_UPC_E = 'UPCE';
+	const TYPE_MSI = 'MSI';
+	const TYPE_MSI_CHECKSUM = 'MSI+';
+	const TYPE_POSTNET = 'POSTNET';
+	const TYPE_PLANET = 'PLANET';
+	const TYPE_RMS4CC = 'RMS4CC';
+	const TYPE_KIX = 'KIX';
+	const TYPE_IMB = 'IMB';
+	const TYPE_CODABAR = 'CODABAR';
+	const TYPE_CODE_11 = 'CODE11';
+	const TYPE_PHARMA_CODE = 'PHARMA';
+	const TYPE_PHARMA_CODE_TWO_TRACKS = 'PHARMA2T';
+
+	/**
+	 * Get the barcode data
+	 *
+	 * @param string $code code to print
+	 * @param string $type type of barcode
+	 * @return array barcode array
+	 * @public
+	 */
+	protected function getBarcodeData($code, $type)
+	{
+		switch (strtoupper($type)) {
+			case self::TYPE_CODE_39:
+				{ // CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
+					$arrcode = $this->barcode_code39($code, false, false);
+					break;
+				}
+			case self::TYPE_CODE_39_CHECKSUM:
+				{ // CODE 39 with checksum
+					$arrcode = $this->barcode_code39($code, false, true);
+					break;
+				}
+			case self::TYPE_CODE_39E:
+				{ // CODE 39 EXTENDED
+					$arrcode = $this->barcode_code39($code, true, false);
+					break;
+				}
+			case self::TYPE_CODE_39E_CHECKSUM:
+				{ // CODE 39 EXTENDED + CHECKSUM
+					$arrcode = $this->barcode_code39($code, true, true);
+					break;
+				}
+			case self::TYPE_CODE_93:
+				{ // CODE 93 - USS-93
+					$arrcode = $this->barcode_code93($code);
+					break;
+				}
+			case self::TYPE_STANDARD_2_5:
+				{ // Standard 2 of 5
+					$arrcode = $this->barcode_s25($code, false);
+					break;
+				}
+			case self::TYPE_STANDARD_2_5_CHECKSUM:
+				{ // Standard 2 of 5 + CHECKSUM
+					$arrcode = $this->barcode_s25($code, true);
+					break;
+				}
+			case self::TYPE_INTERLEAVED_2_5:
+				{ // Interleaved 2 of 5
+					$arrcode = $this->barcode_i25($code, false);
+					break;
+				}
+			case self::TYPE_INTERLEAVED_2_5_CHECKSUM:
+				{ // Interleaved 2 of 5 + CHECKSUM
+					$arrcode = $this->barcode_i25($code, true);
+					break;
+				}
+			case self::TYPE_CODE_128:
+				{ // CODE 128
+					$arrcode = $this->barcode_c128($code, '');
+					break;
+				}
+			case self::TYPE_CODE_128_A:
+				{ // CODE 128 A
+					$arrcode = $this->barcode_c128($code, 'A');
+					break;
+				}
+			case self::TYPE_CODE_128_B:
+				{ // CODE 128 B
+					$arrcode = $this->barcode_c128($code, 'B');
+					break;
+				}
+			case self::TYPE_CODE_128_C:
+				{ // CODE 128 C
+					$arrcode = $this->barcode_c128($code, 'C');
+					break;
+				}
+			case self::TYPE_EAN_2:
+				{ // 2-Digits UPC-Based Extention
+					$arrcode = $this->barcode_eanext($code, 2);
+					break;
+				}
+			case self::TYPE_EAN_5:
+				{ // 5-Digits UPC-Based Extention
+					$arrcode = $this->barcode_eanext($code, 5);
+					break;
+				}
+			case self::TYPE_EAN_8:
+				{ // EAN 8
+					$arrcode = $this->barcode_eanupc($code, 8);
+					break;
+				}
+			case self::TYPE_EAN_13:
+				{ // EAN 13
+					$arrcode = $this->barcode_eanupc($code, 13);
+					break;
+				}
+			case self::TYPE_UPC_A:
+				{ // UPC-A
+					$arrcode = $this->barcode_eanupc($code, 12);
+					break;
+				}
+			case self::TYPE_UPC_E:
+				{ // UPC-E
+					$arrcode = $this->barcode_eanupc($code, 6);
+					break;
+				}
+			case self::TYPE_MSI:
+				{ // MSI (Variation of Plessey code)
+					$arrcode = $this->barcode_msi($code, false);
+					break;
+				}
+			case self::TYPE_MSI_CHECKSUM:
+				{ // MSI + CHECKSUM (modulo 11)
+					$arrcode = $this->barcode_msi($code, true);
+					break;
+				}
+			case self::TYPE_POSTNET:
+				{ // POSTNET
+					$arrcode = $this->barcode_postnet($code, false);
+					break;
+				}
+			case self::TYPE_PLANET:
+				{ // PLANET
+					$arrcode = $this->barcode_postnet($code, true);
+					break;
+				}
+			case self::TYPE_RMS4CC:
+				{ // RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)
+					$arrcode = $this->barcode_rms4cc($code, false);
+					break;
+				}
+			case self::TYPE_KIX:
+				{ // KIX (Klant index - Customer index)
+					$arrcode = $this->barcode_rms4cc($code, true);
+					break;
+				}
+			case self::TYPE_IMB:
+				{ // IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
+					$arrcode = $this->barcode_imb($code);
+					break;
+				}
+			case self::TYPE_CODABAR:
+				{ // CODABAR
+					$arrcode = $this->barcode_codabar($code);
+					break;
+				}
+			case self::TYPE_CODE_11:
+				{ // CODE 11
+					$arrcode = $this->barcode_code11($code);
+					break;
+				}
+			case self::TYPE_PHARMA_CODE:
+				{ // PHARMACODE
+					$arrcode = $this->barcode_pharmacode($code);
+					break;
+				}
+			case self::TYPE_PHARMA_CODE_TWO_TRACKS:
+				{ // PHARMACODE TWO-TRACKS
+					$arrcode = $this->barcode_pharmacode2t($code);
+					break;
+				}
+			default:
+				{
+					throw new UnknownTypeException();
+					break;
+				}
+		}
+
+		if (!isset($arrcode['maxWidth'])) {
+			$arrcode = $this->convertBarcodeArrayToNewStyle($arrcode);
+		}
+
+		return $arrcode;
+	}
+
+	/**
+	 * CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
+	 * General-purpose code in very wide use world-wide
+	 *
+	 * @param $code (string) code to represent.
+	 * @param $extended (boolean) if true uses the extended mode.
+	 * @param $checksum (boolean) if true add a checksum to the code.
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_code39($code, $extended = false, $checksum = false)
+	{
+		$chr = [];
+		$chr['0'] = '111331311';
+		$chr['1'] = '311311113';
+		$chr['2'] = '113311113';
+		$chr['3'] = '313311111';
+		$chr['4'] = '111331113';
+		$chr['5'] = '311331111';
+		$chr['6'] = '113331111';
+		$chr['7'] = '111311313';
+		$chr['8'] = '311311311';
+		$chr['9'] = '113311311';
+		$chr['A'] = '311113113';
+		$chr['B'] = '113113113';
+		$chr['C'] = '313113111';
+		$chr['D'] = '111133113';
+		$chr['E'] = '311133111';
+		$chr['F'] = '113133111';
+		$chr['G'] = '111113313';
+		$chr['H'] = '311113311';
+		$chr['I'] = '113113311';
+		$chr['J'] = '111133311';
+		$chr['K'] = '311111133';
+		$chr['L'] = '113111133';
+		$chr['M'] = '313111131';
+		$chr['N'] = '111131133';
+		$chr['O'] = '311131131';
+		$chr['P'] = '113131131';
+		$chr['Q'] = '111111333';
+		$chr['R'] = '311111331';
+		$chr['S'] = '113111331';
+		$chr['T'] = '111131331';
+		$chr['U'] = '331111113';
+		$chr['V'] = '133111113';
+		$chr['W'] = '333111111';
+		$chr['X'] = '131131113';
+		$chr['Y'] = '331131111';
+		$chr['Z'] = '133131111';
+		$chr['-'] = '131111313';
+		$chr['.'] = '331111311';
+		$chr[' '] = '133111311';
+		$chr['$'] = '131313111';
+		$chr['/'] = '131311131';
+		$chr['+'] = '131113131';
+		$chr['%'] = '111313131';
+		$chr['*'] = '131131311';
+
+		$code = strtoupper($code);
+
+		if ($extended) {
+			// extended mode
+			$code = $this->encode_code39_ext($code);
+		}
+
+		if ($checksum) {
+			// checksum
+			$code .= $this->checksum_code39($code);
+		}
+
+		// add start and stop codes
+		$code = '*' . $code . '*';
+
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
+		$k = 0;
+		$clen = strlen($code);
+		for($i = 0; $i < $clen; ++$i) {
+			$char = $code{$i};
+			if (!isset($chr[$char])) {
+				throw new InvalidCharacterException('Char ' . $char . ' is unsupported');
+			}
+			for($j = 0; $j < 9; ++$j) {
+				if (($j % 2) == 0) {
+					$t = true; // bar
+				} else {
+					$t = false; // space
+				}
+				$w = $chr[$char]{$j};
+				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
+				$bararray['maxw'] += $w;
+				++$k;
+			}
+			// intercharacter gap
+			$bararray['bcode'][$k] = array('t' => false, 'w' => 1, 'h' => 1, 'p' => 0);
+			$bararray['maxw'] += 1;
+			++$k;
+		}
+
+		return $bararray;
+	}
+
+	/**
+	 * Encode a string to be used for CODE 39 Extended mode.
+	 *
+	 * @param string $code code to represent.
+	 * @return bool|string encoded string.
+	 * @protected
+	 */
+	protected function encode_code39_ext($code)
+	{
+		$encode = array(
+			chr(0) => '%U',
+			chr(1) => '$A',
+			chr(2) => '$B',
+			chr(3) => '$C',
+			chr(4) => '$D',
+			chr(5) => '$E',
+			chr(6) => '$F',
+			chr(7) => '$G',
+			chr(8) => '$H',
+			chr(9) => '$I',
+			chr(10) => '$J',
+			chr(11) => '£K',
+			chr(12) => '$L',
+			chr(13) => '$M',
+			chr(14) => '$N',
+			chr(15) => '$O',
+			chr(16) => '$P',
+			chr(17) => '$Q',
+			chr(18) => '$R',
+			chr(19) => '$S',
+			chr(20) => '$T',
+			chr(21) => '$U',
+			chr(22) => '$V',
+			chr(23) => '$W',
+			chr(24) => '$X',
+			chr(25) => '$Y',
+			chr(26) => '$Z',
+			chr(27) => '%A',
+			chr(28) => '%B',
+			chr(29) => '%C',
+			chr(30) => '%D',
+			chr(31) => '%E',
+			chr(32) => ' ',
+			chr(33) => '/A',
+			chr(34) => '/B',
+			chr(35) => '/C',
+			chr(36) => '/D',
+			chr(37) => '/E',
+			chr(38) => '/F',
+			chr(39) => '/G',
+			chr(40) => '/H',
+			chr(41) => '/I',
+			chr(42) => '/J',
+			chr(43) => '/K',
+			chr(44) => '/L',
+			chr(45) => '-',
+			chr(46) => '.',
+			chr(47) => '/O',
+			chr(48) => '0',
+			chr(49) => '1',
+			chr(50) => '2',
+			chr(51) => '3',
+			chr(52) => '4',
+			chr(53) => '5',
+			chr(54) => '6',
+			chr(55) => '7',
+			chr(56) => '8',
+			chr(57) => '9',
+			chr(58) => '/Z',
+			chr(59) => '%F',
+			chr(60) => '%G',
+			chr(61) => '%H',
+			chr(62) => '%I',
+			chr(63) => '%J',
+			chr(64) => '%V',
+			chr(65) => 'A',
+			chr(66) => 'B',
+			chr(67) => 'C',
+			chr(68) => 'D',
+			chr(69) => 'E',
+			chr(70) => 'F',
+			chr(71) => 'G',
+			chr(72) => 'H',
+			chr(73) => 'I',
+			chr(74) => 'J',
+			chr(75) => 'K',
+			chr(76) => 'L',
+			chr(77) => 'M',
+			chr(78) => 'N',
+			chr(79) => 'O',
+			chr(80) => 'P',
+			chr(81) => 'Q',
+			chr(82) => 'R',
+			chr(83) => 'S',
+			chr(84) => 'T',
+			chr(85) => 'U',
+			chr(86) => 'V',
+			chr(87) => 'W',
+			chr(88) => 'X',
+			chr(89) => 'Y',
+			chr(90) => 'Z',
+			chr(91) => '%K',
+			chr(92) => '%L',
+			chr(93) => '%M',
+			chr(94) => '%N',
+			chr(95) => '%O',
+			chr(96) => '%W',
+			chr(97) => '+A',
+			chr(98) => '+B',
+			chr(99) => '+C',
+			chr(100) => '+D',
+			chr(101) => '+E',
+			chr(102) => '+F',
+			chr(103) => '+G',
+			chr(104) => '+H',
+			chr(105) => '+I',
+			chr(106) => '+J',
+			chr(107) => '+K',
+			chr(108) => '+L',
+			chr(109) => '+M',
+			chr(110) => '+N',
+			chr(111) => '+O',
+			chr(112) => '+P',
+			chr(113) => '+Q',
+			chr(114) => '+R',
+			chr(115) => '+S',
+			chr(116) => '+T',
+			chr(117) => '+U',
+			chr(118) => '+V',
+			chr(119) => '+W',
+			chr(120) => '+X',
+			chr(121) => '+Y',
+			chr(122) => '+Z',
+			chr(123) => '%P',
+			chr(124) => '%Q',
+			chr(125) => '%R',
+			chr(126) => '%S',
+			chr(127) => '%T'
+		);
+		$code_ext = '';
+		$clen = strlen($code);
+		for($i = 0; $i < $clen; ++$i) {
+			if (ord($code{$i}) > 127) {
+				throw new InvalidCharacterException('Only supports till char 127');
+			}
+			$code_ext .= $encode[$code{$i}];
+		}
+
+		return $code_ext;
+	}
+
+	/**
+	 * Calculate CODE 39 checksum (modulo 43).
+	 *
+	 * @param string $code code to represent.
+	 * @return string char checksum.
+	 * @protected
+	 */
+	protected function checksum_code39($code)
+	{
+		$chars = array(
+			'0',
+			'1',
+			'2',
+			'3',
+			'4',
+			'5',
+			'6',
+			'7',
+			'8',
+			'9',
+			'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',
+			'-',
+			'.',
+			' ',
+			'$',
+			'/',
+			'+',
+			'%'
+		);
+		$sum = 0;
+		$codelength = strlen($code);
+		for($i = 0; $i < $codelength; ++$i) {
+			$k = array_keys($chars, $code{$i});
+			$sum += $k[0];
+		}
+		$j = ($sum % 43);
+
+		return $chars[$j];
+	}
+
+	/**
+	 * CODE 93 - USS-93
+	 * Compact code similar to Code 39
+	 *
+	 * @param $code (string) code to represent.
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_code93($code)
+	{
+		$chr = [];
+		$chr[48] = '131112'; // 0
+		$chr[49] = '111213'; // 1
+		$chr[50] = '111312'; // 2
+		$chr[51] = '111411'; // 3
+		$chr[52] = '121113'; // 4
+		$chr[53] = '121212'; // 5
+		$chr[54] = '121311'; // 6
+		$chr[55] = '111114'; // 7
+		$chr[56] = '131211'; // 8
+		$chr[57] = '141111'; // 9
+		$chr[65] = '211113'; // A
+		$chr[66] = '211212'; // B
+		$chr[67] = '211311'; // C
+		$chr[68] = '221112'; // D
+		$chr[69] = '221211'; // E
+		$chr[70] = '231111'; // F
+		$chr[71] = '112113'; // G
+		$chr[72] = '112212'; // H
+		$chr[73] = '112311'; // I
+		$chr[74] = '122112'; // J
+		$chr[75] = '132111'; // K
+		$chr[76] = '111123'; // L
+		$chr[77] = '111222'; // M
+		$chr[78] = '111321'; // N
+		$chr[79] = '121122'; // O
+		$chr[80] = '131121'; // P
+		$chr[81] = '212112'; // Q
+		$chr[82] = '212211'; // R
+		$chr[83] = '211122'; // S
+		$chr[84] = '211221'; // T
+		$chr[85] = '221121'; // U
+		$chr[86] = '222111'; // V
+		$chr[87] = '112122'; // W
+		$chr[88] = '112221'; // X
+		$chr[89] = '122121'; // Y
+		$chr[90] = '123111'; // Z
+		$chr[45] = '121131'; // -
+		$chr[46] = '311112'; // .
+		$chr[32] = '311211'; //
+		$chr[36] = '321111'; // $
+		$chr[47] = '112131'; // /
+		$chr[43] = '113121'; // +
+		$chr[37] = '211131'; // %
+		$chr[128] = '121221'; // ($)
+		$chr[129] = '311121'; // (/)
+		$chr[130] = '122211'; // (+)
+		$chr[131] = '312111'; // (%)
+		$chr[42] = '111141'; // start-stop
+		$code = strtoupper($code);
+		$encode = array(
+			chr(0) => chr(131) . 'U',
+			chr(1) => chr(128) . 'A',
+			chr(2) => chr(128) . 'B',
+			chr(3) => chr(128) . 'C',
+			chr(4) => chr(128) . 'D',
+			chr(5) => chr(128) . 'E',
+			chr(6) => chr(128) . 'F',
+			chr(7) => chr(128) . 'G',
+			chr(8) => chr(128) . 'H',
+			chr(9) => chr(128) . 'I',
+			chr(10) => chr(128) . 'J',
+			chr(11) => '£K',
+			chr(12) => chr(128) . 'L',
+			chr(13) => chr(128) . 'M',
+			chr(14) => chr(128) . 'N',
+			chr(15) => chr(128) . 'O',
+			chr(16) => chr(128) . 'P',
+			chr(17) => chr(128) . 'Q',
+			chr(18) => chr(128) . 'R',
+			chr(19) => chr(128) . 'S',
+			chr(20) => chr(128) . 'T',
+			chr(21) => chr(128) . 'U',
+			chr(22) => chr(128) . 'V',
+			chr(23) => chr(128) . 'W',
+			chr(24) => chr(128) . 'X',
+			chr(25) => chr(128) . 'Y',
+			chr(26) => chr(128) . 'Z',
+			chr(27) => chr(131) . 'A',
+			chr(28) => chr(131) . 'B',
+			chr(29) => chr(131) . 'C',
+			chr(30) => chr(131) . 'D',
+			chr(31) => chr(131) . 'E',
+			chr(32) => ' ',
+			chr(33) => chr(129) . 'A',
+			chr(34) => chr(129) . 'B',
+			chr(35) => chr(129) . 'C',
+			chr(36) => chr(129) . 'D',
+			chr(37) => chr(129) . 'E',
+			chr(38) => chr(129) . 'F',
+			chr(39) => chr(129) . 'G',
+			chr(40) => chr(129) . 'H',
+			chr(41) => chr(129) . 'I',
+			chr(42) => chr(129) . 'J',
+			chr(43) => chr(129) . 'K',
+			chr(44) => chr(129) . 'L',
+			chr(45) => '-',
+			chr(46) => '.',
+			chr(47) => chr(129) . 'O',
+			chr(48) => '0',
+			chr(49) => '1',
+			chr(50) => '2',
+			chr(51) => '3',
+			chr(52) => '4',
+			chr(53) => '5',
+			chr(54) => '6',
+			chr(55) => '7',
+			chr(56) => '8',
+			chr(57) => '9',
+			chr(58) => chr(129) . 'Z',
+			chr(59) => chr(131) . 'F',
+			chr(60) => chr(131) . 'G',
+			chr(61) => chr(131) . 'H',
+			chr(62) => chr(131) . 'I',
+			chr(63) => chr(131) . 'J',
+			chr(64) => chr(131) . 'V',
+			chr(65) => 'A',
+			chr(66) => 'B',
+			chr(67) => 'C',
+			chr(68) => 'D',
+			chr(69) => 'E',
+			chr(70) => 'F',
+			chr(71) => 'G',
+			chr(72) => 'H',
+			chr(73) => 'I',
+			chr(74) => 'J',
+			chr(75) => 'K',
+			chr(76) => 'L',
+			chr(77) => 'M',
+			chr(78) => 'N',
+			chr(79) => 'O',
+			chr(80) => 'P',
+			chr(81) => 'Q',
+			chr(82) => 'R',
+			chr(83) => 'S',
+			chr(84) => 'T',
+			chr(85) => 'U',
+			chr(86) => 'V',
+			chr(87) => 'W',
+			chr(88) => 'X',
+			chr(89) => 'Y',
+			chr(90) => 'Z',
+			chr(91) => chr(131) . 'K',
+			chr(92) => chr(131) . 'L',
+			chr(93) => chr(131) . 'M',
+			chr(94) => chr(131) . 'N',
+			chr(95) => chr(131) . 'O',
+			chr(96) => chr(131) . 'W',
+			chr(97) => chr(130) . 'A',
+			chr(98) => chr(130) . 'B',
+			chr(99) => chr(130) . 'C',
+			chr(100) => chr(130) . 'D',
+			chr(101) => chr(130) . 'E',
+			chr(102) => chr(130) . 'F',
+			chr(103) => chr(130) . 'G',
+			chr(104) => chr(130) . 'H',
+			chr(105) => chr(130) . 'I',
+			chr(106) => chr(130) . 'J',
+			chr(107) => chr(130) . 'K',
+			chr(108) => chr(130) . 'L',
+			chr(109) => chr(130) . 'M',
+			chr(110) => chr(130) . 'N',
+			chr(111) => chr(130) . 'O',
+			chr(112) => chr(130) . 'P',
+			chr(113) => chr(130) . 'Q',
+			chr(114) => chr(130) . 'R',
+			chr(115) => chr(130) . 'S',
+			chr(116) => chr(130) . 'T',
+			chr(117) => chr(130) . 'U',
+			chr(118) => chr(130) . 'V',
+			chr(119) => chr(130) . 'W',
+			chr(120) => chr(130) . 'X',
+			chr(121) => chr(130) . 'Y',
+			chr(122) => chr(130) . 'Z',
+			chr(123) => chr(131) . 'P',
+			chr(124) => chr(131) . 'Q',
+			chr(125) => chr(131) . 'R',
+			chr(126) => chr(131) . 'S',
+			chr(127) => chr(131) . 'T'
+		);
+		$code_ext = '';
+		$clen = strlen($code);
+		for($i = 0; $i < $clen; ++$i) {
+			if (ord($code{$i}) > 127) {
+				throw new InvalidCharacterException('Only supports till char 127');
+			}
+			$code_ext .= $encode[$code{$i}];
+		}
+		// checksum
+		$code_ext .= $this->checksum_code93($code_ext);
+		// add start and stop codes
+		$code = '*' . $code_ext . '*';
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
+		$k = 0;
+		$clen = strlen($code);
+		for($i = 0; $i < $clen; ++$i) {
+			$char = ord($code{$i});
+			if (!isset($chr[$char])) {
+				throw new InvalidCharacterException('Char ' . $char . ' is unsupported');
+			}
+			for($j = 0; $j < 6; ++$j) {
+				if (($j % 2) == 0) {
+					$t = true; // bar
+				} else {
+					$t = false; // space
+				}
+				$w = $chr[$char]{$j};
+				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
+				$bararray['maxw'] += $w;
+				++$k;
+			}
+		}
+		$bararray['bcode'][$k] = array('t' => true, 'w' => 1, 'h' => 1, 'p' => 0);
+		$bararray['maxw'] += 1;
+
+		return $bararray;
+	}
+
+	/**
+	 * Calculate CODE 93 checksum (modulo 47).
+	 *
+	 * @param $code (string) code to represent.
+	 * @return string checksum code.
+	 * @protected
+	 */
+	protected function checksum_code93($code)
+	{
+		$chars = array(
+			'0',
+			'1',
+			'2',
+			'3',
+			'4',
+			'5',
+			'6',
+			'7',
+			'8',
+			'9',
+			'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',
+			'-',
+			'.',
+			' ',
+			'$',
+			'/',
+			'+',
+			'%',
+			'<',
+			'=',
+			'>',
+			'?'
+		);
+		// translate special characters
+		$code = strtr($code, chr(128) . chr(131) . chr(129) . chr(130), '<=>?');
+		$len = strlen($code);
+		// calculate check digit C
+		$p = 1;
+		$check = 0;
+		for($i = ($len - 1); $i >= 0; --$i) {
+			$k = array_keys($chars, $code{$i});
+			$check += ($k[0] * $p);
+			++$p;
+			if ($p > 20) {
+				$p = 1;
+			}
+		}
+		$check %= 47;
+		$c = $chars[$check];
+		$code .= $c;
+		// calculate check digit K
+		$p = 1;
+		$check = 0;
+		for($i = $len; $i >= 0; --$i) {
+			$k = array_keys($chars, $code{$i});
+			$check += ($k[0] * $p);
+			++$p;
+			if ($p > 15) {
+				$p = 1;
+			}
+		}
+		$check %= 47;
+		$k = $chars[$check];
+		$checksum = $c . $k;
+		// resto respecial characters
+		$checksum = strtr($checksum, '<=>?', chr(128) . chr(131) . chr(129) . chr(130));
+
+		return $checksum;
+	}
+
+	/**
+	 * Standard 2 of 5 barcodes.
+	 * Used in airline ticket marking, photofinishing
+	 * Contains digits (0 to 9) and encodes the data only in the width of bars.
+	 *
+	 * @param $code (string) code to represent.
+	 * @param $checksum (boolean) if true add a checksum to the code
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_s25($code, $checksum = false)
+	{
+		$chr['0'] = '10101110111010';
+		$chr['1'] = '11101010101110';
+		$chr['2'] = '10111010101110';
+		$chr['3'] = '11101110101010';
+		$chr['4'] = '10101110101110';
+		$chr['5'] = '11101011101010';
+		$chr['6'] = '10111011101010';
+		$chr['7'] = '10101011101110';
+		$chr['8'] = '10101110111010';
+		$chr['9'] = '10111010111010';
+		if ($checksum) {
+			// add checksum
+			$code .= $this->checksum_s25($code);
+		}
+		if ((strlen($code) % 2) != 0) {
+			// add leading zero if code-length is odd
+			$code = '0' . $code;
+		}
+		$seq = '11011010';
+		$clen = strlen($code);
+		for($i = 0; $i < $clen; ++$i) {
+			$digit = $code{$i};
+			if (!isset($chr[$digit])) {
+				throw new InvalidCharacterException('Char ' . $digit . ' is unsupported');
+			}
+			$seq .= $chr[$digit];
+		}
+		$seq .= '1101011';
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
+
+		return $this->binseq_to_array($seq, $bararray);
+	}
+
+	/**
+	 * Checksum for standard 2 of 5 barcodes.
+	 *
+	 * @param $code (string) code to process.
+	 * @return int checksum.
+	 * @protected
+	 */
+	protected function checksum_s25($code)
+	{
+		$len = strlen($code);
+		$sum = 0;
+		for($i = 0; $i < $len; $i += 2) {
+			$sum += $code{$i};
+		}
+		$sum *= 3;
+		for($i = 1; $i < $len; $i += 2) {
+			$sum += ($code{$i});
+		}
+		$r = $sum % 10;
+		if ($r > 0) {
+			$r = (10 - $r);
+		}
+
+		return $r;
+	}
+
+	/**
+	 * Convert binary barcode sequence to TCPDF barcode array.
+	 *
+	 * @param $seq (string) barcode as binary sequence.
+	 * @param $bararray (array) barcode array.
+	 * òparam array $bararray TCPDF barcode array to fill up
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function binseq_to_array($seq, $bararray)
+	{
+		$len = strlen($seq);
+		$w = 0;
+		$k = 0;
+		for($i = 0; $i < $len; ++$i) {
+			$w += 1;
+			if (($i == ($len - 1)) OR (($i < ($len - 1)) AND ($seq{$i} != $seq{($i + 1)}))) {
+				if ($seq{$i} == '1') {
+					$t = true; // bar
+				} else {
+					$t = false; // space
+				}
+				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
+				$bararray['maxw'] += $w;
+				++$k;
+				$w = 0;
+			}
+		}
+
+		return $bararray;
+	}
+
+	/**
+	 * Interleaved 2 of 5 barcodes.
+	 * Compact numeric code, widely used in industry, air cargo
+	 * Contains digits (0 to 9) and encodes the data in the width of both bars and spaces.
+	 *
+	 * @param $code (string) code to represent.
+	 * @param $checksum (boolean) if true add a checksum to the code
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_i25($code, $checksum = false)
+	{
+		$chr['0'] = '11221';
+		$chr['1'] = '21112';
+		$chr['2'] = '12112';
+		$chr['3'] = '22111';
+		$chr['4'] = '11212';
+		$chr['5'] = '21211';
+		$chr['6'] = '12211';
+		$chr['7'] = '11122';
+		$chr['8'] = '21121';
+		$chr['9'] = '12121';
+		$chr['A'] = '11';
+		$chr['Z'] = '21';
+		if ($checksum) {
+			// add checksum
+			$code .= $this->checksum_s25($code);
+		}
+		if ((strlen($code) % 2) != 0) {
+			// add leading zero if code-length is odd
+			$code = '0' . $code;
+		}
+		// add start and stop codes
+		$code = 'AA' . strtolower($code) . 'ZA';
+
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
+		$k = 0;
+		$clen = strlen($code);
+		for($i = 0; $i < $clen; $i = ($i + 2)) {
+			$char_bar = $code{$i};
+			$char_space = $code{$i + 1};
+			if (!isset($chr[$char_bar]) || !isset($chr[$char_space])) {
+				throw new InvalidCharacterException();
+			}
+			// create a bar-space sequence
+			$seq = '';
+			$chrlen = strlen($chr[$char_bar]);
+			for($s = 0; $s < $chrlen; $s++) {
+				$seq .= $chr[$char_bar]{$s} . $chr[$char_space]{$s};
+			}
+			$seqlen = strlen($seq);
+			for($j = 0; $j < $seqlen; ++$j) {
+				if (($j % 2) == 0) {
+					$t = true; // bar
+				} else {
+					$t = false; // space
+				}
+				$w = $seq{$j};
+				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
+				$bararray['maxw'] += $w;
+				++$k;
+			}
+		}
+
+		return $bararray;
+	}
+
+	/**
+	 * C128 barcodes.
+	 * Very capable code, excellent density, high reliability; in very wide use world-wide
+	 *
+	 * @param $code (string) code to represent.
+	 * @param $type (string) barcode type: A, B, C or empty for automatic switch (AUTO mode)
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_c128($code, $type = '')
+	{
+		$chr = array(
+			'212222', /* 00 */
+			'222122', /* 01 */
+			'222221', /* 02 */
+			'121223', /* 03 */
+			'121322', /* 04 */
+			'131222', /* 05 */
+			'122213', /* 06 */
+			'122312', /* 07 */
+			'132212', /* 08 */
+			'221213', /* 09 */
+			'221312', /* 10 */
+			'231212', /* 11 */
+			'112232', /* 12 */
+			'122132', /* 13 */
+			'122231', /* 14 */
+			'113222', /* 15 */
+			'123122', /* 16 */
+			'123221', /* 17 */
+			'223211', /* 18 */
+			'221132', /* 19 */
+			'221231', /* 20 */
+			'213212', /* 21 */
+			'223112', /* 22 */
+			'312131', /* 23 */
+			'311222', /* 24 */
+			'321122', /* 25 */
+			'321221', /* 26 */
+			'312212', /* 27 */
+			'322112', /* 28 */
+			'322211', /* 29 */
+			'212123', /* 30 */
+			'212321', /* 31 */
+			'232121', /* 32 */
+			'111323', /* 33 */
+			'131123', /* 34 */
+			'131321', /* 35 */
+			'112313', /* 36 */
+			'132113', /* 37 */
+			'132311', /* 38 */
+			'211313', /* 39 */
+			'231113', /* 40 */
+			'231311', /* 41 */
+			'112133', /* 42 */
+			'112331', /* 43 */
+			'132131', /* 44 */
+			'113123', /* 45 */
+			'113321', /* 46 */
+			'133121', /* 47 */
+			'313121', /* 48 */
+			'211331', /* 49 */
+			'231131', /* 50 */
+			'213113', /* 51 */
+			'213311', /* 52 */
+			'213131', /* 53 */
+			'311123', /* 54 */
+			'311321', /* 55 */
+			'331121', /* 56 */
+			'312113', /* 57 */
+			'312311', /* 58 */
+			'332111', /* 59 */
+			'314111', /* 60 */
+			'221411', /* 61 */
+			'431111', /* 62 */
+			'111224', /* 63 */
+			'111422', /* 64 */
+			'121124', /* 65 */
+			'121421', /* 66 */
+			'141122', /* 67 */
+			'141221', /* 68 */
+			'112214', /* 69 */
+			'112412', /* 70 */
+			'122114', /* 71 */
+			'122411', /* 72 */
+			'142112', /* 73 */
+			'142211', /* 74 */
+			'241211', /* 75 */
+			'221114', /* 76 */
+			'413111', /* 77 */
+			'241112', /* 78 */
+			'134111', /* 79 */
+			'111242', /* 80 */
+			'121142', /* 81 */
+			'121241', /* 82 */
+			'114212', /* 83 */
+			'124112', /* 84 */
+			'124211', /* 85 */
+			'411212', /* 86 */
+			'421112', /* 87 */
+			'421211', /* 88 */
+			'212141', /* 89 */
+			'214121', /* 90 */
+			'412121', /* 91 */
+			'111143', /* 92 */
+			'111341', /* 93 */
+			'131141', /* 94 */
+			'114113', /* 95 */
+			'114311', /* 96 */
+			'411113', /* 97 */
+			'411311', /* 98 */
+			'113141', /* 99 */
+			'114131', /* 100 */
+			'311141', /* 101 */
+			'411131', /* 102 */
+			'211412', /* 103 START A */
+			'211214', /* 104 START B */
+			'211232', /* 105 START C */
+			'233111', /* STOP */
+			'200000'  /* END */
+		);
+		// ASCII characters for code A (ASCII 00 - 95)
+		$keys_a = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_';
+		$keys_a .= chr(0) . chr(1) . chr(2) . chr(3) . chr(4) . chr(5) . chr(6) . chr(7) . chr(8) . chr(9);
+		$keys_a .= chr(10) . chr(11) . chr(12) . chr(13) . chr(14) . chr(15) . chr(16) . chr(17) . chr(18) . chr(19);
+		$keys_a .= chr(20) . chr(21) . chr(22) . chr(23) . chr(24) . chr(25) . chr(26) . chr(27) . chr(28) . chr(29);
+		$keys_a .= chr(30) . chr(31);
+		// ASCII characters for code B (ASCII 32 - 127)
+		$keys_b = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~' . chr(127);
+		// special codes
+		$fnc_a = array(241 => 102, 242 => 97, 243 => 96, 244 => 101);
+		$fnc_b = array(241 => 102, 242 => 97, 243 => 96, 244 => 100);
+		// array of symbols
+		$code_data = array();
+		// length of the code
+		$len = strlen($code);
+		switch (strtoupper($type)) {
+			case 'A':
+				{ // MODE A
+					$startid = 103;
+					for($i = 0; $i < $len; ++$i) {
+						$char = $code{$i};
+						$char_id = ord($char);
+						if (($char_id >= 241) AND ($char_id <= 244)) {
+							$code_data[] = $fnc_a[$char_id];
+						} elseif (($char_id >= 0) AND ($char_id <= 95)) {
+							$code_data[] = strpos($keys_a, $char);
+						} else {
+							throw new InvalidCharacterException('Char ' . $char . ' is unsupported');
+						}
+					}
+					break;
+				}
+			case 'B':
+				{ // MODE B
+					$startid = 104;
+					for($i = 0; $i < $len; ++$i) {
+						$char = $code{$i};
+						$char_id = ord($char);
+						if (($char_id >= 241) AND ($char_id <= 244)) {
+							$code_data[] = $fnc_b[$char_id];
+						} elseif (($char_id >= 32) AND ($char_id <= 127)) {
+							$code_data[] = strpos($keys_b, $char);
+						} else {
+							throw new InvalidCharacterException('Char ' . $char . ' is unsupported');
+						}
+					}
+					break;
+				}
+			case 'C':
+				{ // MODE C
+					$startid = 105;
+					if (ord($code[0]) == 241) {
+						$code_data[] = 102;
+						$code = substr($code, 1);
+						--$len;
+					}
+					if (($len % 2) != 0) {
+						throw new InvalidLengthException('Length must be even');
+					}
+					for($i = 0; $i < $len; $i += 2) {
+						$chrnum = $code{$i} . $code{$i + 1};
+						if (preg_match('/([0-9]{2})/', $chrnum) > 0) {
+							$code_data[] = intval($chrnum);
+						} else {
+							throw new InvalidCharacterException();
+						}
+					}
+					break;
+				}
+			default:
+				{ // MODE AUTO
+					// split code into sequences
+					$sequence = array();
+					// get numeric sequences (if any)
+					$numseq = array();
+					preg_match_all('/([0-9]{4,})/', $code, $numseq, PREG_OFFSET_CAPTURE);
+					if (isset($numseq[1]) AND !empty($numseq[1])) {
+						$end_offset = 0;
+						foreach($numseq[1] as $val) {
+							$offset = $val[1];
+							if ($offset > $end_offset) {
+								// non numeric sequence
+								$sequence = array_merge($sequence,
+									$this->get128ABsequence(substr($code, $end_offset, ($offset - $end_offset))));
+							}
+							// numeric sequence
+							$slen = strlen($val[0]);
+							if (($slen % 2) != 0) {
+								// the length must be even
+								--$slen;
+							}
+							$sequence[] = array('C', substr($code, $offset, $slen), $slen);
+							$end_offset = $offset + $slen;
+						}
+						if ($end_offset < $len) {
+							$sequence = array_merge($sequence, $this->get128ABsequence(substr($code, $end_offset)));
+						}
+					} else {
+						// text code (non C mode)
+						$sequence = array_merge($sequence, $this->get128ABsequence($code));
+					}
+					// process the sequence
+					foreach($sequence as $key => $seq) {
+						switch ($seq[0]) {
+							case 'A':
+								{
+									if ($key == 0) {
+										$startid = 103;
+									} elseif ($sequence[($key - 1)][0] != 'A') {
+										if (($seq[2] == 1) AND ($key > 0) AND ($sequence[($key - 1)][0] == 'B') AND (!isset($sequence[($key - 1)][3]))) {
+											// single character shift
+											$code_data[] = 98;
+											// mark shift
+											$sequence[$key][3] = true;
+										} elseif (!isset($sequence[($key - 1)][3])) {
+											$code_data[] = 101;
+										}
+									}
+									for($i = 0; $i < $seq[2]; ++$i) {
+										$char = $seq[1]{$i};
+										$char_id = ord($char);
+										if (($char_id >= 241) AND ($char_id <= 244)) {
+											$code_data[] = $fnc_a[$char_id];
+										} else {
+											$code_data[] = strpos($keys_a, $char);
+										}
+									}
+									break;
+								}
+							case 'B':
+								{
+									if ($key == 0) {
+										$tmpchr = ord($seq[1][0]);
+										if (($seq[2] == 1) AND ($tmpchr >= 241) AND ($tmpchr <= 244) AND isset($sequence[($key + 1)]) AND ($sequence[($key + 1)][0] != 'B')) {
+											switch ($sequence[($key + 1)][0]) {
+												case 'A':
+													{
+														$startid = 103;
+														$sequence[$key][0] = 'A';
+														$code_data[] = $fnc_a[$tmpchr];
+														break;
+													}
+												case 'C':
+													{
+														$startid = 105;
+														$sequence[$key][0] = 'C';
+														$code_data[] = $fnc_a[$tmpchr];
+														break;
+													}
+											}
+											break;
+										} else {
+											$startid = 104;
+										}
+									} elseif ($sequence[($key - 1)][0] != 'B') {
+										if (($seq[2] == 1) AND ($key > 0) AND ($sequence[($key - 1)][0] == 'A') AND (!isset($sequence[($key - 1)][3]))) {
+											// single character shift
+											$code_data[] = 98;
+											// mark shift
+											$sequence[$key][3] = true;
+										} elseif (!isset($sequence[($key - 1)][3])) {
+											$code_data[] = 100;
+										}
+									}
+									for($i = 0; $i < $seq[2]; ++$i) {
+										$char = $seq[1]{$i};
+										$char_id = ord($char);
+										if (($char_id >= 241) AND ($char_id <= 244)) {
+											$code_data[] = $fnc_b[$char_id];
+										} else {
+											$code_data[] = strpos($keys_b, $char);
+										}
+									}
+									break;
+								}
+							case 'C':
+								{
+									if ($key == 0) {
+										$startid = 105;
+									} elseif ($sequence[($key - 1)][0] != 'C') {
+										$code_data[] = 99;
+									}
+									for($i = 0; $i < $seq[2]; $i += 2) {
+										$chrnum = $seq[1]{$i} . $seq[1]{$i + 1};
+										$code_data[] = intval($chrnum);
+									}
+									break;
+								}
+						}
+					}
+				}
+		}
+		// calculate check character
+		$sum = $startid;
+		foreach($code_data as $key => $val) {
+			$sum += ($val * ($key + 1));
+		}
+		// add check character
+		$code_data[] = ($sum % 103);
+		// add stop sequence
+		$code_data[] = 106;
+		$code_data[] = 107;
+		// add start code at the beginning
+		array_unshift($code_data, $startid);
+		// build barcode array
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
+		foreach($code_data as $val) {
+			$seq = $chr[$val];
+			for($j = 0; $j < 6; ++$j) {
+				if (($j % 2) == 0) {
+					$t = true; // bar
+				} else {
+					$t = false; // space
+				}
+				$w = $seq{$j};
+				$bararray['bcode'][] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
+				$bararray['maxw'] += $w;
+			}
+		}
+
+		return $bararray;
+	}
+
+	/**
+	 * Split text code in A/B sequence for 128 code
+	 *
+	 * @param $code (string) code to split.
+	 * @return array sequence
+	 * @protected
+	 */
+	protected function get128ABsequence($code)
+	{
+		$len = strlen($code);
+		$sequence = array();
+		// get A sequences (if any)
+		$numseq = array();
+		preg_match_all('/([\x00-\x1f])/', $code, $numseq, PREG_OFFSET_CAPTURE);
+		if (isset($numseq[1]) AND !empty($numseq[1])) {
+			$end_offset = 0;
+			foreach($numseq[1] as $val) {
+				$offset = $val[1];
+				if ($offset > $end_offset) {
+					// B sequence
+					$sequence[] = array(
+						'B',
+						substr($code, $end_offset, ($offset - $end_offset)),
+						($offset - $end_offset)
+					);
+				}
+				// A sequence
+				$slen = strlen($val[0]);
+				$sequence[] = array('A', substr($code, $offset, $slen), $slen);
+				$end_offset = $offset + $slen;
+			}
+			if ($end_offset < $len) {
+				$sequence[] = array('B', substr($code, $end_offset), ($len - $end_offset));
+			}
+		} else {
+			// only B sequence
+			$sequence[] = array('B', $code, $len);
+		}
+
+		return $sequence;
+	}
+
+	/**
+	 * UPC-Based Extensions
+	 * 2-Digit Ext.: Used to indicate magazines and newspaper issue numbers
+	 * 5-Digit Ext.: Used to mark suggested retail price of books
+	 *
+	 * @param $code (string) code to represent.
+	 * @param $len (string) barcode type: 2 = 2-Digit, 5 = 5-Digit
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_eanext($code, $len = 5)
+	{
+		//Padding
+		$code = str_pad($code, $len, '0', STR_PAD_LEFT);
+		// calculate check digit
+		if ($len == 2) {
+			$r = $code % 4;
+		} elseif ($len == 5) {
+			$r = (3 * ($code[0] + $code[2] + $code[4])) + (9 * ($code[1] + $code[3]));
+			$r %= 10;
+		} else {
+			throw new InvalidCheckDigitException();
+		}
+		//Convert digits to bars
+		$codes = array(
+			'A' => array( // left odd parity
+				'0' => '0001101',
+				'1' => '0011001',
+				'2' => '0010011',
+				'3' => '0111101',
+				'4' => '0100011',
+				'5' => '0110001',
+				'6' => '0101111',
+				'7' => '0111011',
+				'8' => '0110111',
+				'9' => '0001011'
+			),
+			'B' => array( // left even parity
+				'0' => '0100111',
+				'1' => '0110011',
+				'2' => '0011011',
+				'3' => '0100001',
+				'4' => '0011101',
+				'5' => '0111001',
+				'6' => '0000101',
+				'7' => '0010001',
+				'8' => '0001001',
+				'9' => '0010111'
+			)
+		);
+		$parities = array();
+		$parities[2] = array(
+			'0' => array('A', 'A'),
+			'1' => array('A', 'B'),
+			'2' => array('B', 'A'),
+			'3' => array('B', 'B')
+		);
+		$parities[5] = array(
+			'0' => array('B', 'B', 'A', 'A', 'A'),
+			'1' => array('B', 'A', 'B', 'A', 'A'),
+			'2' => array('B', 'A', 'A', 'B', 'A'),
+			'3' => array('B', 'A', 'A', 'A', 'B'),
+			'4' => array('A', 'B', 'B', 'A', 'A'),
+			'5' => array('A', 'A', 'B', 'B', 'A'),
+			'6' => array('A', 'A', 'A', 'B', 'B'),
+			'7' => array('A', 'B', 'A', 'B', 'A'),
+			'8' => array('A', 'B', 'A', 'A', 'B'),
+			'9' => array('A', 'A', 'B', 'A', 'B')
+		);
+		$p = $parities[$len][$r];
+		$seq = '1011'; // left guard bar
+		$seq .= $codes[$p[0]][$code[0]];
+		for($i = 1; $i < $len; ++$i) {
+			$seq .= '01'; // separator
+			$seq .= $codes[$p[$i]][$code{$i}];
+		}
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
+
+		return $this->binseq_to_array($seq, $bararray);
+	}
+
+	/**
+	 * EAN13 and UPC-A barcodes.
+	 * EAN13: European Article Numbering international retail product code
+	 * UPC-A: Universal product code seen on almost all retail products in the USA and Canada
+	 * UPC-E: Short version of UPC symbol
+	 *
+	 * @param $code (string) code to represent.
+	 * @param $len (string) barcode type: 6 = UPC-E, 8 = EAN8, 13 = EAN13, 12 = UPC-A
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_eanupc($code, $len = 13)
+	{
+		$upce = false;
+		if ($len == 6) {
+			$len = 12; // UPC-A
+			$upce = true; // UPC-E mode
+		}
+		$data_len = $len - 1;
+		//Padding
+		$code = str_pad($code, $data_len, '0', STR_PAD_LEFT);
+		$code_len = strlen($code);
+		// calculate check digit
+		$sum_a = 0;
+		for($i = 1; $i < $data_len; $i += 2) {
+			$sum_a += $code{$i};
+		}
+		if ($len > 12) {
+			$sum_a *= 3;
+		}
+		$sum_b = 0;
+		for($i = 0; $i < $data_len; $i += 2) {
+			$sum_b += ($code{$i});
+		}
+		if ($len < 13) {
+			$sum_b *= 3;
+		}
+		$r = ($sum_a + $sum_b) % 10;
+		if ($r > 0) {
+			$r = (10 - $r);
+		}
+		if ($code_len == $data_len) {
+			// add check digit
+			$code .= $r;
+		} elseif ($r !== intval($code{$data_len})) {
+			throw new InvalidCheckDigitException();
+		}
+		if ($len == 12) {
+			// UPC-A
+			$code = '0' . $code;
+			++$len;
+		}
+		if ($upce) {
+			// convert UPC-A to UPC-E
+			$tmp = substr($code, 4, 3);
+			if (($tmp == '000') OR ($tmp == '100') OR ($tmp == '200')) {
+				// manufacturer code ends in 000, 100, or 200
+				$upce_code = substr($code, 2, 2) . substr($code, 9, 3) . substr($code, 4, 1);
+			} else {
+				$tmp = substr($code, 5, 2);
+				if ($tmp == '00') {
+					// manufacturer code ends in 00
+					$upce_code = substr($code, 2, 3) . substr($code, 10, 2) . '3';
+				} else {
+					$tmp = substr($code, 6, 1);
+					if ($tmp == '0') {
+						// manufacturer code ends in 0
+						$upce_code = substr($code, 2, 4) . substr($code, 11, 1) . '4';
+					} else {
+						// manufacturer code does not end in zero
+						$upce_code = substr($code, 2, 5) . substr($code, 11, 1);
+					}
+				}
+			}
+		}
+		//Convert digits to bars
+		$codes = array(
+			'A' => array( // left odd parity
+				'0' => '0001101',
+				'1' => '0011001',
+				'2' => '0010011',
+				'3' => '0111101',
+				'4' => '0100011',
+				'5' => '0110001',
+				'6' => '0101111',
+				'7' => '0111011',
+				'8' => '0110111',
+				'9' => '0001011'
+			),
+			'B' => array( // left even parity
+				'0' => '0100111',
+				'1' => '0110011',
+				'2' => '0011011',
+				'3' => '0100001',
+				'4' => '0011101',
+				'5' => '0111001',
+				'6' => '0000101',
+				'7' => '0010001',
+				'8' => '0001001',
+				'9' => '0010111'
+			),
+			'C' => array( // right
+				'0' => '1110010',
+				'1' => '1100110',
+				'2' => '1101100',
+				'3' => '1000010',
+				'4' => '1011100',
+				'5' => '1001110',
+				'6' => '1010000',
+				'7' => '1000100',
+				'8' => '1001000',
+				'9' => '1110100'
+			)
+		);
+		$parities = array(
+			'0' => array('A', 'A', 'A', 'A', 'A', 'A'),
+			'1' => array('A', 'A', 'B', 'A', 'B', 'B'),
+			'2' => array('A', 'A', 'B', 'B', 'A', 'B'),
+			'3' => array('A', 'A', 'B', 'B', 'B', 'A'),
+			'4' => array('A', 'B', 'A', 'A', 'B', 'B'),
+			'5' => array('A', 'B', 'B', 'A', 'A', 'B'),
+			'6' => array('A', 'B', 'B', 'B', 'A', 'A'),
+			'7' => array('A', 'B', 'A', 'B', 'A', 'B'),
+			'8' => array('A', 'B', 'A', 'B', 'B', 'A'),
+			'9' => array('A', 'B', 'B', 'A', 'B', 'A')
+		);
+		$upce_parities = array();
+		$upce_parities[0] = array(
+			'0' => array('B', 'B', 'B', 'A', 'A', 'A'),
+			'1' => array('B', 'B', 'A', 'B', 'A', 'A'),
+			'2' => array('B', 'B', 'A', 'A', 'B', 'A'),
+			'3' => array('B', 'B', 'A', 'A', 'A', 'B'),
+			'4' => array('B', 'A', 'B', 'B', 'A', 'A'),
+			'5' => array('B', 'A', 'A', 'B', 'B', 'A'),
+			'6' => array('B', 'A', 'A', 'A', 'B', 'B'),
+			'7' => array('B', 'A', 'B', 'A', 'B', 'A'),
+			'8' => array('B', 'A', 'B', 'A', 'A', 'B'),
+			'9' => array('B', 'A', 'A', 'B', 'A', 'B')
+		);
+		$upce_parities[1] = array(
+			'0' => array('A', 'A', 'A', 'B', 'B', 'B'),
+			'1' => array('A', 'A', 'B', 'A', 'B', 'B'),
+			'2' => array('A', 'A', 'B', 'B', 'A', 'B'),
+			'3' => array('A', 'A', 'B', 'B', 'B', 'A'),
+			'4' => array('A', 'B', 'A', 'A', 'B', 'B'),
+			'5' => array('A', 'B', 'B', 'A', 'A', 'B'),
+			'6' => array('A', 'B', 'B', 'B', 'A', 'A'),
+			'7' => array('A', 'B', 'A', 'B', 'A', 'B'),
+			'8' => array('A', 'B', 'A', 'B', 'B', 'A'),
+			'9' => array('A', 'B', 'B', 'A', 'B', 'A')
+		);
+		$k = 0;
+		$seq = '101'; // left guard bar
+		if ($upce) {
+			$bararray = array('code' => $upce_code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
+			$p = $upce_parities[$code[1]][$r];
+			for($i = 0; $i < 6; ++$i) {
+				$seq .= $codes[$p[$i]][$upce_code{$i}];
+			}
+			$seq .= '010101'; // right guard bar
+		} else {
+			$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
+			$half_len = intval(ceil($len / 2));
+			if ($len == 8) {
+				for($i = 0; $i < $half_len; ++$i) {
+					$seq .= $codes['A'][$code{$i}];
+				}
+			} else {
+				$p = $parities[$code[0]];
+				for($i = 1; $i < $half_len; ++$i) {
+					$seq .= $codes[$p[$i - 1]][$code{$i}];
+				}
+			}
+			$seq .= '01010'; // center guard bar
+			for($i = $half_len; $i < $len; ++$i) {
+				if (!isset($codes['C'][$code{$i}])) {
+					throw new InvalidCharacterException('Char ' . $code{$i} . ' not allowed');
+				}
+				$seq .= $codes['C'][$code{$i}];
+			}
+			$seq .= '101'; // right guard bar
+		}
+		$clen = strlen($seq);
+		$w = 0;
+		for($i = 0; $i < $clen; ++$i) {
+			$w += 1;
+			if (($i == ($clen - 1)) OR (($i < ($clen - 1)) AND ($seq{$i} != $seq{($i + 1)}))) {
+				if ($seq{$i} == '1') {
+					$t = true; // bar
+				} else {
+					$t = false; // space
+				}
+				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
+				$bararray['maxw'] += $w;
+				++$k;
+				$w = 0;
+			}
+		}
+
+		return $bararray;
+	}
+
+	/**
+	 * MSI.
+	 * Variation of Plessey code, with similar applications
+	 * Contains digits (0 to 9) and encodes the data only in the width of bars.
+	 *
+	 * @param $code (string) code to represent.
+	 * @param $checksum (boolean) if true add a checksum to the code (modulo 11)
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_msi($code, $checksum = false)
+	{
+		$chr['0'] = '100100100100';
+		$chr['1'] = '100100100110';
+		$chr['2'] = '100100110100';
+		$chr['3'] = '100100110110';
+		$chr['4'] = '100110100100';
+		$chr['5'] = '100110100110';
+		$chr['6'] = '100110110100';
+		$chr['7'] = '100110110110';
+		$chr['8'] = '110100100100';
+		$chr['9'] = '110100100110';
+		$chr['A'] = '110100110100';
+		$chr['B'] = '110100110110';
+		$chr['C'] = '110110100100';
+		$chr['D'] = '110110100110';
+		$chr['E'] = '110110110100';
+		$chr['F'] = '110110110110';
+		if ($checksum) {
+			// add checksum
+			$clen = strlen($code);
+			$p = 2;
+			$check = 0;
+			for($i = ($clen - 1); $i >= 0; --$i) {
+				$check += (hexdec($code{$i}) * $p);
+				++$p;
+				if ($p > 7) {
+					$p = 2;
+				}
+			}
+			$check %= 11;
+			if ($check > 0) {
+				$check = 11 - $check;
+			}
+			$code .= $check;
+		}
+		$seq = '110'; // left guard
+		$clen = strlen($code);
+		for($i = 0; $i < $clen; ++$i) {
+			$digit = $code{$i};
+			if (!isset($chr[$digit])) {
+				throw new InvalidCharacterException('Char ' . $digit . ' is unsupported');
+			}
+			$seq .= $chr[$digit];
+		}
+		$seq .= '1001'; // right guard
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
+
+		return $this->binseq_to_array($seq, $bararray);
+	}
+
+	/**
+	 * POSTNET and PLANET barcodes.
+	 * Used by U.S. Postal Service for automated mail sorting
+	 *
+	 * @param $code (string) zip code to represent. Must be a string containing a zip code of the form DDDDD or
+	 *     DDDDD-DDDD.
+	 * @param $planet (boolean) if true print the PLANET barcode, otherwise print POSTNET
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_postnet($code, $planet = false)
+	{
+		// bar length
+		if ($planet) {
+			$barlen = Array(
+				0 => Array(1, 1, 2, 2, 2),
+				1 => Array(2, 2, 2, 1, 1),
+				2 => Array(2, 2, 1, 2, 1),
+				3 => Array(2, 2, 1, 1, 2),
+				4 => Array(2, 1, 2, 2, 1),
+				5 => Array(2, 1, 2, 1, 2),
+				6 => Array(2, 1, 1, 2, 2),
+				7 => Array(1, 2, 2, 2, 1),
+				8 => Array(1, 2, 2, 1, 2),
+				9 => Array(1, 2, 1, 2, 2)
+			);
+		} else {
+			$barlen = Array(
+				0 => Array(2, 2, 1, 1, 1),
+				1 => Array(1, 1, 1, 2, 2),
+				2 => Array(1, 1, 2, 1, 2),
+				3 => Array(1, 1, 2, 2, 1),
+				4 => Array(1, 2, 1, 1, 2),
+				5 => Array(1, 2, 1, 2, 1),
+				6 => Array(1, 2, 2, 1, 1),
+				7 => Array(2, 1, 1, 1, 2),
+				8 => Array(2, 1, 1, 2, 1),
+				9 => Array(2, 1, 2, 1, 1)
+			);
+		}
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
+		$k = 0;
+		$code = str_replace('-', '', $code);
+		$code = str_replace(' ', '', $code);
+		$len = strlen($code);
+		// calculate checksum
+		$sum = 0;
+		for($i = 0; $i < $len; ++$i) {
+			$sum += intval($code{$i});
+		}
+		$chkd = ($sum % 10);
+		if ($chkd > 0) {
+			$chkd = (10 - $chkd);
+		}
+		$code .= $chkd;
+		$len = strlen($code);
+		// start bar
+		$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
+		$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
+		$bararray['maxw'] += 2;
+		for($i = 0; $i < $len; ++$i) {
+			for($j = 0; $j < 5; ++$j) {
+				$h = $barlen[$code{$i}][$j];
+				$p = floor(1 / $h);
+				$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
+				$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
+				$bararray['maxw'] += 2;
+			}
+		}
+		// end bar
+		$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
+		$bararray['maxw'] += 1;
+
+		return $bararray;
+	}
+
+	/**
+	 * RMS4CC - CBC - KIX
+	 * RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) - KIX (Klant index - Customer index)
+	 * RM4SCC is the name of the barcode symbology used by the Royal Mail for its Cleanmail service.
+	 *
+	 * @param $code (string) code to print
+	 * @param $kix (boolean) if true prints the KIX variation (doesn't use the start and end symbols, and the checksum)
+	 *     - in this case the house number must be sufficed with an X and placed at the end of the code.
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_rms4cc($code, $kix = false)
+	{
+		$notkix = !$kix;
+		// bar mode
+		// 1 = pos 1, length 2
+		// 2 = pos 1, length 3
+		// 3 = pos 2, length 1
+		// 4 = pos 2, length 2
+		$barmode = array(
+			'0' => array(3, 3, 2, 2),
+			'1' => array(3, 4, 1, 2),
+			'2' => array(3, 4, 2, 1),
+			'3' => array(4, 3, 1, 2),
+			'4' => array(4, 3, 2, 1),
+			'5' => array(4, 4, 1, 1),
+			'6' => array(3, 1, 4, 2),
+			'7' => array(3, 2, 3, 2),
+			'8' => array(3, 2, 4, 1),
+			'9' => array(4, 1, 3, 2),
+			'A' => array(4, 1, 4, 1),
+			'B' => array(4, 2, 3, 1),
+			'C' => array(3, 1, 2, 4),
+			'D' => array(3, 2, 1, 4),
+			'E' => array(3, 2, 2, 3),
+			'F' => array(4, 1, 1, 4),
+			'G' => array(4, 1, 2, 3),
+			'H' => array(4, 2, 1, 3),
+			'I' => array(1, 3, 4, 2),
+			'J' => array(1, 4, 3, 2),
+			'K' => array(1, 4, 4, 1),
+			'L' => array(2, 3, 3, 2),
+			'M' => array(2, 3, 4, 1),
+			'N' => array(2, 4, 3, 1),
+			'O' => array(1, 3, 2, 4),
+			'P' => array(1, 4, 1, 4),
+			'Q' => array(1, 4, 2, 3),
+			'R' => array(2, 3, 1, 4),
+			'S' => array(2, 3, 2, 3),
+			'T' => array(2, 4, 1, 3),
+			'U' => array(1, 1, 4, 4),
+			'V' => array(1, 2, 3, 4),
+			'W' => array(1, 2, 4, 3),
+			'X' => array(2, 1, 3, 4),
+			'Y' => array(2, 1, 4, 3),
+			'Z' => array(2, 2, 3, 3)
+		);
+		$code = strtoupper($code);
+		$len = strlen($code);
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
+		if ($notkix) {
+			// table for checksum calculation (row,col)
+			$checktable = array(
+				'0' => array(1, 1),
+				'1' => array(1, 2),
+				'2' => array(1, 3),
+				'3' => array(1, 4),
+				'4' => array(1, 5),
+				'5' => array(1, 0),
+				'6' => array(2, 1),
+				'7' => array(2, 2),
+				'8' => array(2, 3),
+				'9' => array(2, 4),
+				'A' => array(2, 5),
+				'B' => array(2, 0),
+				'C' => array(3, 1),
+				'D' => array(3, 2),
+				'E' => array(3, 3),
+				'F' => array(3, 4),
+				'G' => array(3, 5),
+				'H' => array(3, 0),
+				'I' => array(4, 1),
+				'J' => array(4, 2),
+				'K' => array(4, 3),
+				'L' => array(4, 4),
+				'M' => array(4, 5),
+				'N' => array(4, 0),
+				'O' => array(5, 1),
+				'P' => array(5, 2),
+				'Q' => array(5, 3),
+				'R' => array(5, 4),
+				'S' => array(5, 5),
+				'T' => array(5, 0),
+				'U' => array(0, 1),
+				'V' => array(0, 2),
+				'W' => array(0, 3),
+				'X' => array(0, 4),
+				'Y' => array(0, 5),
+				'Z' => array(0, 0)
+			);
+			$row = 0;
+			$col = 0;
+			for($i = 0; $i < $len; ++$i) {
+				$row += $checktable[$code{$i}][0];
+				$col += $checktable[$code{$i}][1];
+			}
+			$row %= 6;
+			$col %= 6;
+			$chk = array_keys($checktable, array($row, $col));
+			$code .= $chk[0];
+			++$len;
+		}
+		$k = 0;
+		if ($notkix) {
+			// start bar
+			$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
+			$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
+			$bararray['maxw'] += 2;
+		}
+		for($i = 0; $i < $len; ++$i) {
+			for($j = 0; $j < 4; ++$j) {
+				switch ($barmode[$code{$i}][$j]) {
+					case 1:
+						{
+							$p = 0;
+							$h = 2;
+							break;
+						}
+					case 2:
+						{
+							$p = 0;
+							$h = 3;
+							break;
+						}
+					case 3:
+						{
+							$p = 1;
+							$h = 1;
+							break;
+						}
+					case 4:
+						{
+							$p = 1;
+							$h = 2;
+							break;
+						}
+				}
+				$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
+				$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
+				$bararray['maxw'] += 2;
+			}
+		}
+		if ($notkix) {
+			// stop bar
+			$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 3, 'p' => 0);
+			$bararray['maxw'] += 1;
+		}
+
+		return $bararray;
+	}
+
+	/**
+	 * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
+	 * (requires PHP bcmath extension)
+	 * Intelligent Mail barcode is a 65-bar code for use on mail in the United States.
+	 * The fields are described as follows:<ul><li>The Barcode Identifier shall be assigned by USPS to encode the
+	 * presort identification that is currently printed in human readable form on the optional endorsement line (OEL)
+	 * as well as for future USPS use. This shall be two digits, with the second digit in the range of 0–4. The
+	 * allowable encoding ranges shall be 00–04, 10–14, 20–24, 30–34, 40–44, 50–54, 60–64, 70–74, 80–84, and
+	 * 90–94.</li><li>The Service Type Identifier shall be assigned by USPS for any combination of services requested
+	 * on the mailpiece. The allowable encoding range shall be 000http://it2.php.net/manual/en/function.dechex.php–999.
+	 * Each 3-digit value shall correspond to a particular mail class with a particular combination of service(s). Each
+	 * service program, such as OneCode Confirm and OneCode ACS, shall provide the list of Service Type Identifier
+	 * values.</li><li>The Mailer or Customer Identifier shall be assigned by USPS as a unique, 6 or 9 digit number
+	 * that identifies a business entity. The allowable encoding range for the 6 digit Mailer ID shall be 000000-
+	 * 899999, while the allowable encoding range for the 9 digit Mailer ID shall be 900000000-999999999.</li><li>The
+	 * Serial or Sequence Number shall be assigned by the mailer for uniquely identifying and tracking mailpieces. The
+	 * allowable encoding range shall be 000000000–999999999 when used with a 6 digit Mailer ID and 000000-999999 when
+	 * used with a 9 digit Mailer ID. e. The Delivery Point ZIP Code shall be assigned by the mailer for routing the
+	 * mailpiece. This shall replace POSTNET for routing the mailpiece to its final delivery point. The length may be
+	 * 0, 5, 9, or 11 digits. The allowable encoding ranges shall be no ZIP Code, 00000–99999,  000000000–999999999,
+	 * and 00000000000–99999999999.</li></ul>
+	 *
+	 * @param $code (string) code to print, separate the ZIP (routing code) from the rest using a minus char '-'
+	 *     (BarcodeID_ServiceTypeID_MailerID_SerialNumber-RoutingCode)
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_imb($code)
+	{
+		$asc_chr = array(
+			4,
+			0,
+			2,
+			6,
+			3,
+			5,
+			1,
+			9,
+			8,
+			7,
+			1,
+			2,
+			0,
+			6,
+			4,
+			8,
+			2,
+			9,
+			5,
+			3,
+			0,
+			1,
+			3,
+			7,
+			4,
+			6,
+			8,
+			9,
+			2,
+			0,
+			5,
+			1,
+			9,
+			4,
+			3,
+			8,
+			6,
+			7,
+			1,
+			2,
+			4,
+			3,
+			9,
+			5,
+			7,
+			8,
+			3,
+			0,
+			2,
+			1,
+			4,
+			0,
+			9,
+			1,
+			7,
+			0,
+			2,
+			4,
+			6,
+			3,
+			7,
+			1,
+			9,
+			5,
+			8
+		);
+		$dsc_chr = array(
+			7,
+			1,
+			9,
+			5,
+			8,
+			0,
+			2,
+			4,
+			6,
+			3,
+			5,
+			8,
+			9,
+			7,
+			3,
+			0,
+			6,
+			1,
+			7,
+			4,
+			6,
+			8,
+			9,
+			2,
+			5,
+			1,
+			7,
+			5,
+			4,
+			3,
+			8,
+			7,
+			6,
+			0,
+			2,
+			5,
+			4,
+			9,
+			3,
+			0,
+			1,
+			6,
+			8,
+			2,
+			0,
+			4,
+			5,
+			9,
+			6,
+			7,
+			5,
+			2,
+			6,
+			3,
+			8,
+			5,
+			1,
+			9,
+			8,
+			7,
+			4,
+			0,
+			2,
+			6,
+			3
+		);
+		$asc_pos = array(
+			3,
+			0,
+			8,
+			11,
+			1,
+			12,
+			8,
+			11,
+			10,
+			6,
+			4,
+			12,
+			2,
+			7,
+			9,
+			6,
+			7,
+			9,
+			2,
+			8,
+			4,
+			0,
+			12,
+			7,
+			10,
+			9,
+			0,
+			7,
+			10,
+			5,
+			7,
+			9,
+			6,
+			8,
+			2,
+			12,
+			1,
+			4,
+			2,
+			0,
+			1,
+			5,
+			4,
+			6,
+			12,
+			1,
+			0,
+			9,
+			4,
+			7,
+			5,
+			10,
+			2,
+			6,
+			9,
+			11,
+			2,
+			12,
+			6,
+			7,
+			5,
+			11,
+			0,
+			3,
+			2
+		);
+		$dsc_pos = array(
+			2,
+			10,
+			12,
+			5,
+			9,
+			1,
+			5,
+			4,
+			3,
+			9,
+			11,
+			5,
+			10,
+			1,
+			6,
+			3,
+			4,
+			1,
+			10,
+			0,
+			2,
+			11,
+			8,
+			6,
+			1,
+			12,
+			3,
+			8,
+			6,
+			4,
+			4,
+			11,
+			0,
+			6,
+			1,
+			9,
+			11,
+			5,
+			3,
+			7,
+			3,
+			10,
+			7,
+			11,
+			8,
+			2,
+			10,
+			3,
+			5,
+			8,
+			0,
+			3,
+			12,
+			11,
+			8,
+			4,
+			5,
+			1,
+			3,
+			0,
+			7,
+			12,
+			9,
+			8,
+			10
+		);
+		$code_arr = explode('-', $code);
+		$tracking_number = $code_arr[0];
+		if (isset($code_arr[1])) {
+			$routing_code = $code_arr[1];
+		} else {
+			$routing_code = '';
+		}
+		// Conversion of Routing Code
+		switch (strlen($routing_code)) {
+			case 0:
+				{
+					$binary_code = 0;
+					break;
+				}
+			case 5:
+				{
+					$binary_code = bcadd($routing_code, '1');
+					break;
+				}
+			case 9:
+				{
+					$binary_code = bcadd($routing_code, '100001');
+					break;
+				}
+			case 11:
+				{
+					$binary_code = bcadd($routing_code, '1000100001');
+					break;
+				}
+			default:
+				{
+					throw new BarcodeException('Routing code unknown');
+					break;
+				}
+		}
+		$binary_code = bcmul($binary_code, 10);
+		$binary_code = bcadd($binary_code, $tracking_number[0]);
+		$binary_code = bcmul($binary_code, 5);
+		$binary_code = bcadd($binary_code, $tracking_number[1]);
+		$binary_code .= substr($tracking_number, 2, 18);
+		// convert to hexadecimal
+		$binary_code = $this->dec_to_hex($binary_code);
+		// pad to get 13 bytes
+		$binary_code = str_pad($binary_code, 26, '0', STR_PAD_LEFT);
+		// convert string to array of bytes
+		$binary_code_arr = chunk_split($binary_code, 2, "\r");
+		$binary_code_arr = substr($binary_code_arr, 0, -1);
+		$binary_code_arr = explode("\r", $binary_code_arr);
+		// calculate frame check sequence
+		$fcs = $this->imb_crc11fcs($binary_code_arr);
+		// exclude first 2 bits from first byte
+		$first_byte = sprintf('%2s', dechex((hexdec($binary_code_arr[0]) << 2) >> 2));
+		$binary_code_102bit = $first_byte . substr($binary_code, 2);
+		// convert binary data to codewords
+		$codewords = array();
+		$data = $this->hex_to_dec($binary_code_102bit);
+		$codewords[0] = bcmod($data, 636) * 2;
+		$data = bcdiv($data, 636);
+		for($i = 1; $i < 9; ++$i) {
+			$codewords[$i] = bcmod($data, 1365);
+			$data = bcdiv($data, 1365);
+		}
+		$codewords[9] = $data;
+		if (($fcs >> 10) == 1) {
+			$codewords[9] += 659;
+		}
+		// generate lookup tables
+		$table2of13 = $this->imb_tables(2, 78);
+		$table5of13 = $this->imb_tables(5, 1287);
+		// convert codewords to characters
+		$characters = array();
+		$bitmask = 512;
+		foreach($codewords as $k => $val) {
+			if ($val <= 1286) {
+				$chrcode = $table5of13[$val];
+			} else {
+				$chrcode = $table2of13[($val - 1287)];
+			}
+			if (($fcs & $bitmask) > 0) {
+				// bitwise invert
+				$chrcode = ((~$chrcode) & 8191);
+			}
+			$characters[] = $chrcode;
+			$bitmask /= 2;
+		}
+		$characters = array_reverse($characters);
+		// build bars
+		$k = 0;
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
+		for($i = 0; $i < 65; ++$i) {
+			$asc = (($characters[$asc_chr[$i]] & pow(2, $asc_pos[$i])) > 0);
+			$dsc = (($characters[$dsc_chr[$i]] & pow(2, $dsc_pos[$i])) > 0);
+			if ($asc AND $dsc) {
+				// full bar (F)
+				$p = 0;
+				$h = 3;
+			} elseif ($asc) {
+				// ascender (A)
+				$p = 0;
+				$h = 2;
+			} elseif ($dsc) {
+				// descender (D)
+				$p = 1;
+				$h = 2;
+			} else {
+				// tracker (T)
+				$p = 1;
+				$h = 1;
+			}
+			$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
+			$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
+			$bararray['maxw'] += 2;
+		}
+		unset($bararray['bcode'][($k - 1)]);
+		--$bararray['maxw'];
+
+		return $bararray;
+	}
+
+	/**
+	 * Convert large integer number to hexadecimal representation.
+	 * (requires PHP bcmath extension)
+	 *
+	 * @param $number (string) number to convert specified as a string
+	 * @return string hexadecimal representation
+	 */
+	protected function dec_to_hex($number)
+	{
+		if ($number == 0) {
+			return '00';
+		}
+
+		$hex = [];
+
+		while ($number > 0) {
+			array_push($hex, strtoupper(dechex(bcmod($number, '16'))));
+			$number = bcdiv($number, '16', 0);
+		}
+		$hex = array_reverse($hex);
+
+		return implode($hex);
+	}
+
+	/**
+	 * Intelligent Mail Barcode calculation of Frame Check Sequence
+	 *
+	 * @param $code_arr (string) array of hexadecimal values (13 bytes holding 102 bits right justified).
+	 * @return int 11 bit Frame Check Sequence as integer (decimal base)
+	 * @protected
+	 */
+	protected function imb_crc11fcs($code_arr)
+	{
+		$genpoly = 0x0F35; // generator polynomial
+		$fcs = 0x07FF; // Frame Check Sequence
+		// do most significant byte skipping the 2 most significant bits
+		$data = hexdec($code_arr[0]) << 5;
+		for($bit = 2; $bit < 8; ++$bit) {
+			if (($fcs ^ $data) & 0x400) {
+				$fcs = ($fcs << 1) ^ $genpoly;
+			} else {
+				$fcs = ($fcs << 1);
+			}
+			$fcs &= 0x7FF;
+			$data <<= 1;
+		}
+		// do rest of bytes
+		for($byte = 1; $byte < 13; ++$byte) {
+			$data = hexdec($code_arr[$byte]) << 3;
+			for($bit = 0; $bit < 8; ++$bit) {
+				if (($fcs ^ $data) & 0x400) {
+					$fcs = ($fcs << 1) ^ $genpoly;
+				} else {
+					$fcs = ($fcs << 1);
+				}
+				$fcs &= 0x7FF;
+				$data <<= 1;
+			}
+		}
+
+		return $fcs;
+	}
+
+	/**
+	 * Convert large hexadecimal number to decimal representation (string).
+	 * (requires PHP bcmath extension)
+	 *
+	 * @param $hex (string) hexadecimal number to convert specified as a string
+	 * @return string hexadecimal representation
+	 */
+	protected function hex_to_dec($hex)
+	{
+		$dec = 0;
+		$bitval = 1;
+		$len = strlen($hex);
+		for($pos = ($len - 1); $pos >= 0; --$pos) {
+			$dec = bcadd($dec, bcmul(hexdec($hex{$pos}), $bitval));
+			$bitval = bcmul($bitval, 16);
+		}
+
+		return $dec;
+	}
+
+	/**
+	 * generate Nof13 tables used for Intelligent Mail Barcode
+	 *
+	 * @param $n (int) is the type of table: 2 for 2of13 table, 5 for 5of13table
+	 * @param $size (int) size of table (78 for n=2 and 1287 for n=5)
+	 * @return array requested table
+	 * @protected
+	 */
+	protected function imb_tables($n, $size)
+	{
+		$table = array();
+		$lli = 0; // LUT lower index
+		$lui = $size - 1; // LUT upper index
+		for($count = 0; $count < 8192; ++$count) {
+			$bit_count = 0;
+			for($bit_index = 0; $bit_index < 13; ++$bit_index) {
+				$bit_count += intval(($count & (1 << $bit_index)) != 0);
+			}
+			// if we don't have the right number of bits on, go on to the next value
+			if ($bit_count == $n) {
+				$reverse = ($this->imb_reverse_us($count) >> 3);
+				// if the reverse is less than count, we have already visited this pair before
+				if ($reverse >= $count) {
+					// If count is symmetric, place it at the first free slot from the end of the list.
+					// Otherwise, place it at the first free slot from the beginning of the list AND place $reverse ath the next free slot from the beginning of the list
+					if ($reverse == $count) {
+						$table[$lui] = $count;
+						--$lui;
+					} else {
+						$table[$lli] = $count;
+						++$lli;
+						$table[$lli] = $reverse;
+						++$lli;
+					}
+				}
+			}
+		}
+
+		return $table;
+	}
+
+	/**
+	 * Reverse unsigned short value
+	 *
+	 * @param $num (int) value to reversr
+	 * @return int reversed value
+	 * @protected
+	 */
+	protected function imb_reverse_us($num)
+	{
+		$rev = 0;
+		for($i = 0; $i < 16; ++$i) {
+			$rev <<= 1;
+			$rev |= ($num & 1);
+			$num >>= 1;
+		}
+
+		return $rev;
+	}
+
+	/**
+	 * CODABAR barcodes.
+	 * Older code often used in library systems, sometimes in blood banks
+	 *
+	 * @param $code (string) code to represent.
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_codabar($code)
+	{
+		$chr = array(
+			'0' => '11111221',
+			'1' => '11112211',
+			'2' => '11121121',
+			'3' => '22111111',
+			'4' => '11211211',
+			'5' => '21111211',
+			'6' => '12111121',
+			'7' => '12112111',
+			'8' => '12211111',
+			'9' => '21121111',
+			'-' => '11122111',
+			'$' => '11221111',
+			':' => '21112121',
+			'/' => '21211121',
+			'.' => '21212111',
+			'+' => '11222221',
+			'A' => '11221211',
+			'B' => '12121121',
+			'C' => '11121221',
+			'D' => '11122211'
+		);
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
+		$k = 0;
+		$w = 0;
+		$seq = '';
+		$code = 'A' . strtoupper($code) . 'A';
+		$len = strlen($code);
+		for($i = 0; $i < $len; ++$i) {
+			if (!isset($chr[$code{$i}])) {
+				throw new InvalidCharacterException('Char ' . $code{$i} . ' is unsupported');
+			}
+			$seq = $chr[$code{$i}];
+			for($j = 0; $j < 8; ++$j) {
+				if (($j % 2) == 0) {
+					$t = true; // bar
+				} else {
+					$t = false; // space
+				}
+				$w = $seq{$j};
+				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
+				$bararray['maxw'] += $w;
+				++$k;
+			}
+		}
+
+		return $bararray;
+	}
+
+	/**
+	 * CODE11 barcodes.
+	 * Used primarily for labeling telecommunications equipment
+	 *
+	 * @param $code (string) code to represent.
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_code11($code)
+	{
+		$chr = array(
+			'0' => '111121',
+			'1' => '211121',
+			'2' => '121121',
+			'3' => '221111',
+			'4' => '112121',
+			'5' => '212111',
+			'6' => '122111',
+			'7' => '111221',
+			'8' => '211211',
+			'9' => '211111',
+			'-' => '112111',
+			'S' => '112211'
+		);
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
+		$k = 0;
+		$w = 0;
+		$seq = '';
+		$len = strlen($code);
+		// calculate check digit C
+		$p = 1;
+		$check = 0;
+		for($i = ($len - 1); $i >= 0; --$i) {
+			$digit = $code{$i};
+			if ($digit == '-') {
+				$dval = 10;
+			} else {
+				$dval = intval($digit);
+			}
+			$check += ($dval * $p);
+			++$p;
+			if ($p > 10) {
+				$p = 1;
+			}
+		}
+		$check %= 11;
+		if ($check == 10) {
+			$check = '-';
+		}
+		$code .= $check;
+		if ($len > 10) {
+			// calculate check digit K
+			$p = 1;
+			$check = 0;
+			for($i = $len; $i >= 0; --$i) {
+				$digit = $code{$i};
+				if ($digit == '-') {
+					$dval = 10;
+				} else {
+					$dval = intval($digit);
+				}
+				$check += ($dval * $p);
+				++$p;
+				if ($p > 9) {
+					$p = 1;
+				}
+			}
+			$check %= 11;
+			$code .= $check;
+			++$len;
+		}
+		$code = 'S' . $code . 'S';
+		$len += 3;
+		for($i = 0; $i < $len; ++$i) {
+			if (!isset($chr[$code{$i}])) {
+				throw new InvalidCharacterException('Char ' . $code{$i} . ' is unsupported');
+			}
+			$seq = $chr[$code{$i}];
+			for($j = 0; $j < 6; ++$j) {
+				if (($j % 2) == 0) {
+					$t = true; // bar
+				} else {
+					$t = false; // space
+				}
+				$w = $seq{$j};
+				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
+				$bararray['maxw'] += $w;
+				++$k;
+			}
+		}
+
+		return $bararray;
+	}
+
+	/**
+	 * Pharmacode
+	 * Contains digits (0 to 9)
+	 *
+	 * @param $code (string) code to represent.
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_pharmacode($code)
+	{
+		$seq = '';
+		$code = intval($code);
+		while ($code > 0) {
+			if (($code % 2) == 0) {
+				$seq .= '11100';
+				$code -= 2;
+			} else {
+				$seq .= '100';
+				$code -= 1;
+			}
+			$code /= 2;
+		}
+		$seq = substr($seq, 0, -2);
+		$seq = strrev($seq);
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
+
+		return $this->binseq_to_array($seq, $bararray);
+	}
+
+	/**
+	 * Pharmacode two-track
+	 * Contains digits (0 to 9)
+	 *
+	 * @param $code (string) code to represent.
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_pharmacode2t($code)
+	{
+		$seq = '';
+		$code = intval($code);
+		do {
+			switch ($code % 3) {
+				case 0:
+					{
+						$seq .= '3';
+						$code = ($code - 3) / 3;
+						break;
+					}
+				case 1:
+					{
+						$seq .= '1';
+						$code = ($code - 1) / 3;
+						break;
+					}
+				case 2:
+					{
+						$seq .= '2';
+						$code = ($code - 2) / 3;
+						break;
+					}
+			}
+		} while ($code != 0);
+		$seq = strrev($seq);
+		$k = 0;
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
+		$len = strlen($seq);
+		for($i = 0; $i < $len; ++$i) {
+			switch ($seq{$i}) {
+				case '1':
+					{
+						$p = 1;
+						$h = 1;
+						break;
+					}
+				case '2':
+					{
+						$p = 0;
+						$h = 1;
+						break;
+					}
+				case '3':
+					{
+						$p = 0;
+						$h = 2;
+						break;
+					}
+			}
+			$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
+			$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
+			$bararray['maxw'] += 2;
+		}
+		unset($bararray['bcode'][($k - 1)]);
+		--$bararray['maxw'];
+
+		return $bararray;
+	}
+
+	protected function convertBarcodeArrayToNewStyle($oldBarcodeArray)
+	{
+		$newBarcodeArray = [];
+		$newBarcodeArray['code'] = $oldBarcodeArray['code'];
+		$newBarcodeArray['maxWidth'] = $oldBarcodeArray['maxw'];
+		$newBarcodeArray['maxHeight'] = $oldBarcodeArray['maxh'];
+		$newBarcodeArray['bars'] = [];
+		foreach($oldBarcodeArray['bcode'] as $oldbar) {
+			$newBar = [];
+			$newBar['width'] = $oldbar['w'];
+			$newBar['height'] = $oldbar['h'];
+			$newBar['positionVertical'] = $oldbar['p'];
+			$newBar['drawBar'] = $oldbar['t'];
+			$newBar['drawSpacing'] = !$oldbar['t'];
+
+			$newBarcodeArray['bars'][] = $newBar;
+		}
+
+		return $newBarcodeArray;
+	}
+
+	/**
+	 * IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
+	 *
+	 * @param $code (string) pre-formatted IMB barcode (65 chars "FADT")
+	 * @return array barcode representation.
+	 * @protected
+	 */
+	protected function barcode_imb_pre($code)
+	{
+		if (!preg_match('/^[fadtFADT]{65}$/', $code) == 1) {
+			throw new InvalidFormatException();
+		}
+		$characters = str_split(strtolower($code), 1);
+		// build bars
+		$k = 0;
+		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
+		for($i = 0; $i < 65; ++$i) {
+			switch ($characters[$i]) {
+				case 'f':
+					{
+						// full bar
+						$p = 0;
+						$h = 3;
+						break;
+					}
+				case 'a':
+					{
+						// ascender
+						$p = 0;
+						$h = 2;
+						break;
+					}
+				case 'd':
+					{
+						// descender
+						$p = 1;
+						$h = 2;
+						break;
+					}
+				case 't':
+					{
+						// tracker (short)
+						$p = 1;
+						$h = 1;
+						break;
+					}
+			}
+			$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
+			$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
+			$bararray['maxw'] += 2;
+		}
+		unset($bararray['bcode'][($k - 1)]);
+		--$bararray['maxw'];
+
+		return $bararray;
+	}
 }

+ 35 - 35
src/Picqer/Barcode/BarcodeGeneratorHTML.php

@@ -5,39 +5,39 @@ namespace Picqer\Barcode;
 class BarcodeGeneratorHTML extends BarcodeGenerator
 {
 
-    /**
-     * Return an HTML representation of barcode.
-     *
-     * @param string $code code to print
-     * @param string $type type of barcode
-     * @param int $widthFactor Width of a single bar element in pixels.
-     * @param int $totalHeight Height of a single bar element in pixels.
-     * @param int|string $color Foreground color for bar elements (background is transparent).
-     * @return string HTML code.
-     * @public
-     */
-    public function getBarcode($code, $type, $widthFactor = 2, $totalHeight = 30, $color = 'black')
-    {
-        $barcodeData = $this->getBarcodeData($code, $type);
-
-        $html = '<div style="font-size:0;position:relative;width:' . ($barcodeData['maxWidth'] * $widthFactor) . 'px;height:' . ($totalHeight) . 'px;">' . "\n";
-
-        $positionHorizontal = 0;
-        foreach ($barcodeData['bars'] as $bar) {
-            $barWidth = round(($bar['width'] * $widthFactor), 3);
-            $barHeight = round(($bar['height'] * $totalHeight / $barcodeData['maxHeight']), 3);
-
-            if ($bar['drawBar']) {
-                $positionVertical = round(($bar['positionVertical'] * $totalHeight / $barcodeData['maxHeight']), 3);
-                // draw a vertical bar
-                $html .= '<div style="background-color:' . $color . ';width:' . $barWidth . 'px;height:' . $barHeight . 'px;position:absolute;left:' . $positionHorizontal . 'px;top:' . $positionVertical . 'px;">&nbsp;</div>' . "\n";
-            }
-
-            $positionHorizontal += $barWidth;
-        }
-
-        $html .= '</div>' . "\n";
-
-        return $html;
-    }
+	/**
+	 * Return an HTML representation of barcode.
+	 *
+	 * @param string $code code to print
+	 * @param string $type type of barcode
+	 * @param int $widthFactor Width of a single bar element in pixels.
+	 * @param int $totalHeight Height of a single bar element in pixels.
+	 * @param int|string $color Foreground color for bar elements (background is transparent).
+	 * @return string HTML code.
+	 * @public
+	 */
+	public function getBarcode($code, $type, $widthFactor = 2, $totalHeight = 30, $color = 'black')
+	{
+		$barcodeData = $this->getBarcodeData($code, $type);
+
+		$html = '<div style="font-size:0;position:relative;width:' . ($barcodeData['maxWidth'] * $widthFactor) . 'px;height:' . ($totalHeight) . 'px;">' . "\n";
+
+		$positionHorizontal = 0;
+		foreach($barcodeData['bars'] as $bar) {
+			$barWidth = round(($bar['width'] * $widthFactor), 3);
+			$barHeight = round(($bar['height'] * $totalHeight / $barcodeData['maxHeight']), 3);
+
+			if ($bar['drawBar']) {
+				$positionVertical = round(($bar['positionVertical'] * $totalHeight / $barcodeData['maxHeight']), 3);
+				// draw a vertical bar
+				$html .= '<div style="background-color:' . $color . ';width:' . $barWidth . 'px;height:' . $barHeight . 'px;position:absolute;left:' . $positionHorizontal . 'px;top:' . $positionVertical . 'px;">&nbsp;</div>' . "\n";
+			}
+
+			$positionHorizontal += $barWidth;
+		}
+
+		$html .= '</div>' . "\n";
+
+		return $html;
+	}
 }

+ 63 - 63
src/Picqer/Barcode/BarcodeGeneratorJPG.php

@@ -7,71 +7,71 @@ use Picqer\Barcode\Exceptions\BarcodeException;
 class BarcodeGeneratorJPG extends BarcodeGenerator
 {
 
-    /**
-     * Return a JPG image representation of barcode (requires GD or Imagick library).
-     *
-     * @param string $code code to print
-     * @param string $type type of barcode:
-     * @param int $widthFactor Width of a single bar element in pixels.
-     * @param int $totalHeight Height of a single bar element in pixels.
-     * @param array $color RGB (0-255) foreground color for bar elements (background is transparent).
-     * @return string image data or false in case of error.
-     * @public
-     * @throws BarcodeException
-     */
-    public function getBarcode($code, $type, $widthFactor = 2, $totalHeight = 30, $color = array(0, 0, 0))
-    {
-        $barcodeData = $this->getBarcodeData($code, $type);
+	/**
+	 * Return a JPG image representation of barcode (requires GD or Imagick library).
+	 *
+	 * @param string $code code to print
+	 * @param string $type type of barcode:
+	 * @param int $widthFactor Width of a single bar element in pixels.
+	 * @param int $totalHeight Height of a single bar element in pixels.
+	 * @param array $color RGB (0-255) foreground color for bar elements (background is transparent).
+	 * @return string image data or false in case of error.
+	 * @public
+	 * @throws BarcodeException
+	 */
+	public function getBarcode($code, $type, $widthFactor = 2, $totalHeight = 30, $color = array(0, 0, 0))
+	{
+		$barcodeData = $this->getBarcodeData($code, $type);
 
-        // calculate image size
-        $width = ($barcodeData['maxWidth'] * $widthFactor);
-        $height = $totalHeight;
+		// calculate image size
+		$width = ($barcodeData['maxWidth'] * $widthFactor);
+		$height = $totalHeight;
 
-        if (function_exists('imagecreate')) {
-            // GD library
-            $imagick = false;
-            $jpg = imagecreate($width, $height);
-            $colorBackground = imagecolorallocate($jpg, 255, 255, 255);
-            imagecolortransparent($jpg, $colorBackground);
-            $colorForeground = imagecolorallocate($jpg, $color[0], $color[1], $color[2]);
-        } elseif (extension_loaded('imagick')) {
-            $imagick = true;
-            $colorForeground = new \imagickpixel('rgb(' . $color[0] . ',' . $color[1] . ',' . $color[2] . ')');
-            $jpg = new \Imagick();
-            $jpg->newImage($width, $height, 'none', 'jpg');
-            $imageMagickObject = new \imagickdraw();
-            $imageMagickObject->setFillColor($colorForeground);
-        } else {
-            throw new BarcodeException('Neither gd-lib or imagick are installed!');
-        }
+		if (function_exists('imagecreate')) {
+			// GD library
+			$imagick = false;
+			$jpg = imagecreate($width, $height);
+			$colorBackground = imagecolorallocate($jpg, 255, 255, 255);
+			imagecolortransparent($jpg, $colorBackground);
+			$colorForeground = imagecolorallocate($jpg, $color[0], $color[1], $color[2]);
+		} elseif (extension_loaded('imagick')) {
+			$imagick = true;
+			$colorForeground = new \imagickpixel('rgb(' . $color[0] . ',' . $color[1] . ',' . $color[2] . ')');
+			$jpg = new \Imagick();
+			$jpg->newImage($width, $height, 'none', 'jpg');
+			$imageMagickObject = new \imagickdraw();
+			$imageMagickObject->setFillColor($colorForeground);
+		} else {
+			throw new BarcodeException('Neither gd-lib or imagick are installed!');
+		}
 
-        // print bars
-        $positionHorizontal = 0;
-        foreach ($barcodeData['bars'] as $bar) {
-            $bw = round(($bar['width'] * $widthFactor), 3);
-            $bh = round(($bar['height'] * $totalHeight / $barcodeData['maxHeight']), 3);
-            if ($bar['drawBar']) {
-                $y = round(($bar['positionVertical'] * $totalHeight / $barcodeData['maxHeight']), 3);
-                // draw a vertical bar
-                if ($imagick && isset($imageMagickObject)) {
-                    $imageMagickObject->rectangle($positionHorizontal, $y, ($positionHorizontal + $bw), ($y + $bh));
-                } else {
-                    imagefilledrectangle($jpg, $positionHorizontal, $y, ($positionHorizontal + $bw) - 1, ($y + $bh),
-                        $colorForeground);
-                }
-            }
-            $positionHorizontal += $bw;
-        }
-        ob_start();
-        if ($imagick && isset($imageMagickObject)) {
-            $jpg->drawImage($imageMagickObject);
-            echo $jpg;
-        } else {
-            imagejpeg($jpg);
-            imagedestroy($jpg);
-        }
-        $image = ob_get_clean();
+		// print bars
+		$positionHorizontal = 0;
+		foreach($barcodeData['bars'] as $bar) {
+			$bw = round(($bar['width'] * $widthFactor), 3);
+			$bh = round(($bar['height'] * $totalHeight / $barcodeData['maxHeight']), 3);
+			if ($bar['drawBar']) {
+				$y = round(($bar['positionVertical'] * $totalHeight / $barcodeData['maxHeight']), 3);
+				// draw a vertical bar
+				if ($imagick && isset($imageMagickObject)) {
+					$imageMagickObject->rectangle($positionHorizontal, $y, ($positionHorizontal + $bw), ($y + $bh));
+				} else {
+					imagefilledrectangle($jpg, $positionHorizontal, $y, ($positionHorizontal + $bw) - 1, ($y + $bh),
+						$colorForeground);
+				}
+			}
+			$positionHorizontal += $bw;
+		}
+		ob_start();
+		if ($imagick && isset($imageMagickObject)) {
+			$jpg->drawImage($imageMagickObject);
+			echo $jpg;
+		} else {
+			imagejpeg($jpg);
+			imagedestroy($jpg);
+		}
+		$image = ob_get_clean();
 
-        return $image;
-    }
+		return $image;
+	}
 }

+ 62 - 62
src/Picqer/Barcode/BarcodeGeneratorPNG.php

@@ -7,70 +7,70 @@ use Picqer\Barcode\Exceptions\BarcodeException;
 class BarcodeGeneratorPNG extends BarcodeGenerator
 {
 
-    /**
-     * Return a PNG image representation of barcode (requires GD or Imagick library).
-     *
-     * @param string $code code to print
-     * @param string $type type of barcode:
-     * @param int $widthFactor Width of a single bar element in pixels.
-     * @param int $totalHeight Height of a single bar element in pixels.
-     * @param array $color RGB (0-255) foreground color for bar elements (background is transparent).
-     * @return string image data or false in case of error.
-     * @public
-     */
-    public function getBarcode($code, $type, $widthFactor = 2, $totalHeight = 30, $color = array(0, 0, 0))
-    {
-        $barcodeData = $this->getBarcodeData($code, $type);
+	/**
+	 * Return a PNG image representation of barcode (requires GD or Imagick library).
+	 *
+	 * @param string $code code to print
+	 * @param string $type type of barcode:
+	 * @param int $widthFactor Width of a single bar element in pixels.
+	 * @param int $totalHeight Height of a single bar element in pixels.
+	 * @param array $color RGB (0-255) foreground color for bar elements (background is transparent).
+	 * @return string image data or false in case of error.
+	 * @public
+	 */
+	public function getBarcode($code, $type, $widthFactor = 2, $totalHeight = 30, $color = array(0, 0, 0))
+	{
+		$barcodeData = $this->getBarcodeData($code, $type);
 
-        // calculate image size
-        $width = ($barcodeData['maxWidth'] * $widthFactor);
-        $height = $totalHeight;
+		// calculate image size
+		$width = ($barcodeData['maxWidth'] * $widthFactor);
+		$height = $totalHeight;
 
-        if (function_exists('imagecreate')) {
-            // GD library
-            $imagick = false;
-            $png = imagecreate($width, $height);
-            $colorBackground = imagecolorallocate($png, 255, 255, 255);
-            imagecolortransparent($png, $colorBackground);
-            $colorForeground = imagecolorallocate($png, $color[0], $color[1], $color[2]);
-        } elseif (extension_loaded('imagick')) {
-            $imagick = true;
-            $colorForeground = new \imagickpixel('rgb(' . $color[0] . ',' . $color[1] . ',' . $color[2] . ')');
-            $png = new \Imagick();
-            $png->newImage($width, $height, 'none', 'png');
-            $imageMagickObject = new \imagickdraw();
-            $imageMagickObject->setFillColor($colorForeground);
-        } else {
-            throw new BarcodeException('Neither gd-lib or imagick are installed!');
-        }
+		if (function_exists('imagecreate')) {
+			// GD library
+			$imagick = false;
+			$png = imagecreate($width, $height);
+			$colorBackground = imagecolorallocate($png, 255, 255, 255);
+			imagecolortransparent($png, $colorBackground);
+			$colorForeground = imagecolorallocate($png, $color[0], $color[1], $color[2]);
+		} elseif (extension_loaded('imagick')) {
+			$imagick = true;
+			$colorForeground = new \imagickpixel('rgb(' . $color[0] . ',' . $color[1] . ',' . $color[2] . ')');
+			$png = new \Imagick();
+			$png->newImage($width, $height, 'none', 'png');
+			$imageMagickObject = new \imagickdraw();
+			$imageMagickObject->setFillColor($colorForeground);
+		} else {
+			throw new BarcodeException('Neither gd-lib or imagick are installed!');
+		}
 
-        // print bars
-        $positionHorizontal = 0;
-        foreach ($barcodeData['bars'] as $bar) {
-            $bw = round(($bar['width'] * $widthFactor), 3);
-            $bh = round(($bar['height'] * $totalHeight / $barcodeData['maxHeight']), 3);
-            if ($bar['drawBar']) {
-                $y = round(($bar['positionVertical'] * $totalHeight / $barcodeData['maxHeight']), 3);
-                // draw a vertical bar
-                if ($imagick && isset($imageMagickObject)) {
-                    $imageMagickObject->rectangle($positionHorizontal, $y, ($positionHorizontal + $bw), ($y + $bh));
-                } else {
-                    imagefilledrectangle($png, $positionHorizontal, $y, ($positionHorizontal + $bw) - 1, ($y + $bh),
-                        $colorForeground);
-                }
-            }
-            $positionHorizontal += $bw;
-        }
-        ob_start();
-        if ($imagick && isset($imageMagickObject)) {
-            $png->drawImage($imageMagickObject);
-            echo $png;
-        } else {
-            imagepng($png);
-            imagedestroy($png);
-        }
-        $image = ob_get_clean();
+		// print bars
+		$positionHorizontal = 0;
+		foreach($barcodeData['bars'] as $bar) {
+			$bw = round(($bar['width'] * $widthFactor), 3);
+			$bh = round(($bar['height'] * $totalHeight / $barcodeData['maxHeight']), 3);
+			if ($bar['drawBar']) {
+				$y = round(($bar['positionVertical'] * $totalHeight / $barcodeData['maxHeight']), 3);
+				// draw a vertical bar
+				if ($imagick && isset($imageMagickObject)) {
+					$imageMagickObject->rectangle($positionHorizontal, $y, ($positionHorizontal + $bw), ($y + $bh));
+				} else {
+					imagefilledrectangle($png, $positionHorizontal, $y, ($positionHorizontal + $bw) - 1, ($y + $bh),
+						$colorForeground);
+				}
+			}
+			$positionHorizontal += $bw;
+		}
+		ob_start();
+		if ($imagick && isset($imageMagickObject)) {
+			$png->drawImage($imageMagickObject);
+			echo $png;
+		} else {
+			imagepng($png);
+			imagedestroy($png);
+		}
+		$image = ob_get_clean();
 
-        return $image;
-    }
+		return $image;
+	}
 }

+ 38 - 38
src/Picqer/Barcode/BarcodeGeneratorSVG.php

@@ -5,45 +5,45 @@ namespace Picqer\Barcode;
 class BarcodeGeneratorSVG extends BarcodeGenerator
 {
 
-    /**
-     * Return a SVG string representation of barcode.
-     *
-     * @param $code (string) code to print
-     * @param $type (const) type of barcode
-     * @param $widthFactor (int) Minimum width of a single bar in user units.
-     * @param $totalHeight (int) Height of barcode in user units.
-     * @param $color (string) Foreground color (in SVG format) for bar elements (background is transparent).
-     * @return string SVG code.
-     * @public
-     */
-    public function getBarcode($code, $type, $widthFactor = 2, $totalHeight = 30, $color = 'black')
-    {
-        $barcodeData = $this->getBarcodeData($code, $type);
+	/**
+	 * Return a SVG string representation of barcode.
+	 *
+	 * @param $code (string) code to print
+	 * @param $type (const) type of barcode
+	 * @param $widthFactor (int) Minimum width of a single bar in user units.
+	 * @param $totalHeight (int) Height of barcode in user units.
+	 * @param $color (string) Foreground color (in SVG format) for bar elements (background is transparent).
+	 * @return string SVG code.
+	 * @public
+	 */
+	public function getBarcode($code, $type, $widthFactor = 2, $totalHeight = 30, $color = 'black')
+	{
+		$barcodeData = $this->getBarcodeData($code, $type);
 
-        // replace table for special characters
-        $repstr = array("\0" => '', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;');
+		// replace table for special characters
+		$repstr = array("\0" => '', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;');
 
-        $svg = '<?xml version="1.0" standalone="no" ?>' . "\n";
-        $svg .= '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' . "\n";
-        $svg .= '<svg width="' . round(($barcodeData['maxWidth'] * $widthFactor),
-                3) . '" height="' . $totalHeight . '" version="1.1" xmlns="http://www.w3.org/2000/svg">' . "\n";
-        $svg .= "\t" . '<desc>' . strtr($barcodeData['code'], $repstr) . '</desc>' . "\n";
-        $svg .= "\t" . '<g id="bars" fill="' . $color . '" stroke="none">' . "\n";
-        // print bars
-        $positionHorizontal = 0;
-        foreach ($barcodeData['bars'] as $bar) {
-            $barWidth = round(($bar['width'] * $widthFactor), 3);
-            $barHeight = round(($bar['height'] * $totalHeight / $barcodeData['maxHeight']), 3);
-            if ($bar['drawBar']) {
-                $positionVertical = round(($bar['positionVertical'] * $totalHeight / $barcodeData['maxHeight']), 3);
-                // draw a vertical bar
-                $svg .= "\t\t" . '<rect x="' . $positionHorizontal . '" y="' . $positionVertical . '" width="' . $barWidth . '" height="' . $barHeight . '" />' . "\n";
-            }
-            $positionHorizontal += $barWidth;
-        }
-        $svg .= "\t" . '</g>' . "\n";
-        $svg .= '</svg>' . "\n";
+		$svg = '<?xml version="1.0" standalone="no" ?>' . "\n";
+		$svg .= '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' . "\n";
+		$svg .= '<svg width="' . round(($barcodeData['maxWidth'] * $widthFactor),
+				3) . '" height="' . $totalHeight . '" version="1.1" xmlns="http://www.w3.org/2000/svg">' . "\n";
+		$svg .= "\t" . '<desc>' . strtr($barcodeData['code'], $repstr) . '</desc>' . "\n";
+		$svg .= "\t" . '<g id="bars" fill="' . $color . '" stroke="none">' . "\n";
+		// print bars
+		$positionHorizontal = 0;
+		foreach($barcodeData['bars'] as $bar) {
+			$barWidth = round(($bar['width'] * $widthFactor), 3);
+			$barHeight = round(($bar['height'] * $totalHeight / $barcodeData['maxHeight']), 3);
+			if ($bar['drawBar']) {
+				$positionVertical = round(($bar['positionVertical'] * $totalHeight / $barcodeData['maxHeight']), 3);
+				// draw a vertical bar
+				$svg .= "\t\t" . '<rect x="' . $positionHorizontal . '" y="' . $positionVertical . '" width="' . $barWidth . '" height="' . $barHeight . '" />' . "\n";
+			}
+			$positionHorizontal += $barWidth;
+		}
+		$svg .= "\t" . '</g>' . "\n";
+		$svg .= '</svg>' . "\n";
 
-        return $svg;
-    }
+		return $svg;
+	}
 }

+ 3 - 1
src/Picqer/Barcode/Exceptions/BarcodeException.php

@@ -2,4 +2,6 @@
 
 namespace Picqer\Barcode\Exceptions;
 
-class BarcodeException extends \Exception {}
+class BarcodeException extends \Exception
+{
+}

+ 3 - 1
src/Picqer/Barcode/Exceptions/InvalidCharacterException.php

@@ -2,4 +2,6 @@
 
 namespace Picqer\Barcode\Exceptions;
 
-class InvalidCharacterException extends BarcodeException {}
+class InvalidCharacterException extends BarcodeException
+{
+}

+ 3 - 1
src/Picqer/Barcode/Exceptions/InvalidCheckDigitException.php

@@ -2,4 +2,6 @@
 
 namespace Picqer\Barcode\Exceptions;
 
-class InvalidCheckDigitException extends BarcodeException {}
+class InvalidCheckDigitException extends BarcodeException
+{
+}

+ 3 - 1
src/Picqer/Barcode/Exceptions/InvalidFormatException.php

@@ -2,4 +2,6 @@
 
 namespace Picqer\Barcode\Exceptions;
 
-class InvalidFormatException extends BarcodeException {}
+class InvalidFormatException extends BarcodeException
+{
+}

+ 3 - 1
src/Picqer/Barcode/Exceptions/InvalidLengthException.php

@@ -2,4 +2,6 @@
 
 namespace Picqer\Barcode\Exceptions;
 
-class InvalidLengthException extends BarcodeException {}
+class InvalidLengthException extends BarcodeException
+{
+}

+ 3 - 1
src/Picqer/Barcode/Exceptions/UnknownTypeException.php

@@ -2,4 +2,6 @@
 
 namespace Picqer\Barcode\Exceptions;
 
-class UnknownTypeException extends BarcodeException {}
+class UnknownTypeException extends BarcodeException
+{
+}

+ 6 - 5
ui/bind.tpl

@@ -25,17 +25,18 @@
 						<tbody>
 						<repeat group="{{ @LISTE }}" key="{{@key}}" value="{{ @LISTA }}">
 							<tr>
-								<td {{(@key==0)? 'class="blink bg-success text-black font-weight-bold"': ''}}>{{@LISTA.commessa}}</td>
+								<td {{(@key==0)?
+								'class="blink bg-success text-black font-weight-bold"': ''}}>{{@LISTA.commessa}}</td>
 							</tr>
 						</repeat>
 						</tbody>
 					</table>
 
 				</div>
-				<form class="form" method="post" action="{{@BASEURL}}/bind">
-					<input type="hidden" value="{{@ORDINE}}" hidden name="commessa"/>
-					<input type="submit" hidden id="submitform"/>
-					<input type="text" name="labelid" class="form-control form-control" placeholder="Etichetta Cesta" required autofocus forcefocus autocomplete="off" value=""/>
+				<form action="{{@BASEURL}}/bind" class="form" method="post">
+					<input hidden name="commessa" type="hidden" value="{{@ORDINE}}"/>
+					<input hidden id="submitform" type="submit"/>
+					<input autocomplete="off" autofocus class="form-control form-control" forcefocus name="labelid" placeholder="Etichetta Cesta" required type="text" value=""/>
 				</form>
 			</true>
 		</check>

+ 69 - 70
ui/css/omlink.scss

@@ -27,41 +27,41 @@ $inputColor: white;
 $placeholderColor: gray !important;
 
 .navbar.fixed-bottom {
-  color: white;
+	color: white;
 }
 
 html, body {
-  height: 100%;
+	height: 100%;
 }
 
 body {
-  background-color: $mainColor !important;
-  color: $textColor !important;
-  font-family: 'Roboto';
+	background-color: $mainColor !important;
+	color: $textColor !important;
+	font-family: 'Roboto';
 }
 
 /* latin */
 @font-face {
-  font-family: 'Roboto';
-  font-style: normal;
-  font-weight: 400;
-  src: local('Roboto'), local('Roboto-Regular'), url('ui/fonts/Roboto-Regular.ttf') format('truetype');
-  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
+	font-family: 'Roboto';
+	font-style: normal;
+	font-weight: 400;
+	src: local('Roboto'), local('Roboto-Regular'), url('ui/fonts/Roboto-Regular.ttf') format('truetype');
+	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
 }
 
 .error_body:before {
-  content: "";
-  position: absolute;
-  left: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  background: url('ui/images/error_bg.png');
-  background-size: cover;
+	content: "";
+	position: absolute;
+	left: 0;
+	top: 0;
+	width: 100%;
+	height: 100%;
+	background: url('ui/images/error_bg.png');
+	background-size: cover;
 }
 
 .error_body .card {
-  opacity: 0.9;
+	opacity: 0.9;
 }
 
 /*
@@ -87,107 +87,106 @@ input:focus {
 }*/
 
 .form-control, .btn {
-  background-color: $inputBgColor !important;
-  color: $inputColor !important;
+	background-color: $inputBgColor !important;
+	color: $inputColor !important;
 }
 
 .form-control:focus, .btn:focus {
-  //  border-color: #c5ac0f !important;
-  background-color: lighten($inputBgColor, 8%) !important;
-  border-color: darken($inputBgColor, 10%) !important;
-  box-shadow: 0 0 10px $inputBgColor !important;
+	//  border-color: #c5ac0f !important;
+	background-color: lighten($inputBgColor, 8%) !important;
+	border-color: darken($inputBgColor, 10%) !important;
+	box-shadow: 0 0 10px $inputBgColor !important;
 }
 
 .form-control:disabled {
-  color: darken($inputColor, 10%) !important;
-  background-color: darken($inputBgColor, 8%) !important;
+	color: darken($inputColor, 10%) !important;
+	background-color: darken($inputBgColor, 8%) !important;
 }
 
 .debugborder {
-  border: 1px solid red !important;
+	border: 1px solid red !important;
 }
 
 .disablebutton {
-  opacity: 0.4;
+	opacity: 0.4;
 }
 
 .imgbuttonmenu {
-  max-height: 180px !important;
-  border-radius: 10px !important;
+	max-height: 180px !important;
+	border-radius: 10px !important;
 }
 
 .om-shadow {
-  filter: drop-shadow(0px 0.2em 5px $shadowColor);
+	filter: drop-shadow(0px 0.2em 5px $shadowColor);
 }
 
 input::placeholder {
-  color: $placeholderColor;
+	color: $placeholderColor;
 }
 
 input::-ms-input-placeholder {
-  color: $placeholderColor;
+	color: $placeholderColor;
 }
 
 .navbar {
-  background-color: $navbarsColor !important;
+	background-color: $navbarsColor !important;
 }
 
 .rounded {
-  border-radius: 15px !important;
+	border-radius: 15px !important;
 }
 
 @mixin prefix($property, $parameters...) {
-  @each $prefix in -webkit-, -moz-, -ms-, -o-, "" {
-    #{$prefix}#{$property}: $parameters;
-  }
+	@each $prefix in -webkit-, -moz-, -ms-, -o-, "" {
+		#{$prefix}#{$property}: $parameters;
+	}
 }
 
 // Blink Effect
 @keyframes blink {
-  0% {
-    @include prefix(opacity, 0.1);
-    // background-color: lighten(#28a745, 40%);
-  }
-  100% {
-    @include prefix(opacity, 1);
-    // background-color: darken(#28a745, 10%);
-  }
+	0% {
+		@include prefix(opacity, 0.1);
+		// background-color: lighten(#28a745, 40%);
+	}
+	100% {
+		@include prefix(opacity, 1);
+		// background-color: darken(#28a745, 10%);
+	}
 }
 
 @-webkit-keyframes blink {
-  0% {
-    @include prefix(opacity, 0.1);
-    // background-color: lighten(#28a745, 40%);
-  }
-  100% {
-    @include prefix(opacity, 1);
-    // background-color: darken(#28a745, 10%);
-  }
+	0% {
+		@include prefix(opacity, 0.1);
+		// background-color: lighten(#28a745, 40%);
+	}
+	100% {
+		@include prefix(opacity, 1);
+		// background-color: darken(#28a745, 10%);
+	}
 }
 
 .blink {
-  @include prefix(transition, all 0.1s ease-in-out);
-  @include prefix(animation, blink alternate 1s infinite ease-in-out);
+	@include prefix(transition, all 0.1s ease-in-out);
+	@include prefix(animation, blink alternate 1s infinite ease-in-out);
 }
 
 #sysmsgnum {
-  color: white;
-  background-color: red;
-  font-size: 40%;
-  position: absolute;
-  left: 15px;
-  bottom: 0;
+	color: white;
+	background-color: red;
+	font-size: 40%;
+	position: absolute;
+	left: 15px;
+	bottom: 0;
 }
 
 #notification_area {
-  padding-bottom: 0;
-  border-radius: 10px 10px
+	padding-bottom: 0;
+	border-radius: 10px 10px
 }
 
 #notification_area_deleteall {
-  background-color: #3380BD;
-  color: white;
-  border-radius: 0 0 10px 10px;
-  padding: 0;
+	background-color: #3380BD;
+	color: white;
+	border-radius: 0 0 10px 10px;
+	padding: 0;
 }
-

+ 2 - 2
ui/errors.tpl

@@ -2,9 +2,9 @@
 <html lang="it">
 <head>
 	<meta charset="UTF-8">
-	<meta name="viewport" content="width=device-width, initial-scale=1">
+	<meta content="width=device-width, initial-scale=1" name="viewport">
 	<title>{{@SITENAME}} error page</title>
-	<link type="text/css" rel="stylesheet" href="{{@BASEURL}}/bundle.css"/>
+	<link href="{{@BASEURL}}/bundle.css" rel="stylesheet" type="text/css"/>
 </head>
 <body class="bg-light error_body">
 

+ 2 - 2
ui/footer.tpl

@@ -1,13 +1,13 @@
 <nav class="navbar fixed-bottom navbar-expand navbar-dark">
 	<check if="{{ isset(@PREVPAGE) }}">
-		<a href="{{@PREVPAGE}}"><img class="navbar-brand" src="{{@BASEURL}}/ui/images/arrow-left.svg" height="50px"/></a>
+		<a href="{{@PREVPAGE}}"><img class="navbar-brand" height="50px" src="{{@BASEURL}}/ui/images/arrow-left.svg"/></a>
 	</check>
 	<div class="nav-item">Utente: {{@COOKIE.username}}</div>
 	<div class="collapse navbar-collapse"></div>
 	<div class="nav-item text-dark pr-2" style="font-size: 0.7em">Version: {{@VERSION}}</div>
 	<div class="navbar-brand">
 		<a href="{{@BASEURL}}">
-			<img src="{{@BASEURL}}/ui/images/om-link-logo.png" height="40"/>
+			<img height="40" src="{{@BASEURL}}/ui/images/om-link-logo.png"/>
 		</a>
 	</div>
 </nav>

+ 6 - 6
ui/header.tpl

@@ -1,6 +1,6 @@
 <nav class="navbar navbar-expand-sm navbar-dark bg-dark om-shadow">
 	<a href="{{@BASEURL}}/"><img class="img-fluid om-shadow navbar-brand customerlogo" src="{{@LOGO_CUSTOMER}}"/></a>
-	<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#headerMenu" aria-controls="headerMenu" aria-expanded="false" aria-label="Toggle navigation">
+	<button aria-controls="headerMenu" aria-expanded="false" aria-label="Toggle navigation" class="navbar-toggler" data-target="#headerMenu" data-toggle="collapse" type="button">
 		<span class="navbar-toggler-icon"></span>
 	</button>
 
@@ -9,7 +9,7 @@
 			<repeat group="{{@GLOBALMENU}}" key="{{ @ikey }}" value="{{@menuitem}}">
 				<check if="{{ !empty(@menuitem.url) }}">
 					<li class="nav-item">
-						<a role="button" class="nav-link btn btn-secondary" href="{{@BASEURL . '/' . @menuitem.url}}">{{@ikey}}</a>
+						<a class="nav-link btn btn-secondary" href="{{@BASEURL . '/' . @menuitem.url}}" role="button">{{@ikey}}</a>
 					</li>
 				</check>
 			</repeat>
@@ -17,13 +17,13 @@
 	</div>
 
 	<div class="ml-auto dropdown dropleft navbar-brand">
-		<a id="notification_area_button" class="disabled" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="mr-3" style="position: relative">
+		<a aria-expanded="false" aria-haspopup="true" class="disabled" class="mr-3" data-toggle="dropdown" href="#" id="notification_area_button" style="position: relative">
 			<img src="{{@BASEURL}}/ui/images/bell.png"/>
-			<span id="sysmsgnum" class="blink badge badge-light"></span>
+			<span class="blink badge badge-light" id="sysmsgnum"></span>
 		</a>
-		<div id="notification_area" class="dropdown-menu" aria-labelledby="dropdownMenuButton"></div>
+		<div aria-labelledby="dropdownMenuButton" class="dropdown-menu" id="notification_area"></div>
 	</div>
 	<div>
-		<a href="{{@BASEURL}}/logout"><img src="{{@ICON_LOGOUT}}" class="img-fluid om-shadow"/></a>
+		<a href="{{@BASEURL}}/logout"><img class="img-fluid om-shadow" src="{{@ICON_LOGOUT}}"/></a>
 	</div>
 </nav>

File diff suppressed because it is too large
+ 179 - 179
ui/images/svg/disegno.svg


+ 71 - 71
ui/js/omlink.js

@@ -10,12 +10,12 @@ let CUSTOM_NOTIFY = 0x4000;
 let REFRESH_FILTERS = CUSTOM_NOTIFY + 1;
 
 const fetchHeaders = {
-  'Accept': 'text/html',
-  'Content-Type': 'text/html',
-  'X-Requested-With': 'XMLHttpRequest',
-  'Cache-Control': 'no-cache',
-  'Pragma': 'no-cache',
-  'Expires': '0'
+	'Accept': 'text/html',
+	'Content-Type': 'text/html',
+	'X-Requested-With': 'XMLHttpRequest',
+	'Cache-Control': 'no-cache',
+	'Pragma': 'no-cache',
+	'Expires': '0'
 };
 
 /* usefull if a blinking text is need, like in MaxMara project, you need to place this code in html:
@@ -25,99 +25,99 @@ const fetchHeaders = {
  * </nav>
  */
 function SetStatusBarText(msg) {
-  $('#statusbartext').text(msg);
-  setTimeout(() => {
-    $('#statusbartext').text('');
-  }, 60000);
+	$('#statusbartext').text(msg);
+	setTimeout(() => {
+		$('#statusbartext').text('');
+	}, 60000);
 }
 
 function NotificationBuilder(notifications) {
-  let tplNotify = '';
-  let htmlNotificationArea = '';
-  if (notifications.length === 0) {
-    $('#notification_area_button').addClass('disabled');
-    $('#sysmsgnum').empty();
-  } else {
-    let notificationCount = 0;
-    notifications.forEach(function (element) {
+	let tplNotify = '';
+	let htmlNotificationArea = '';
+	if (notifications.length === 0) {
+		$('#notification_area_button').addClass('disabled');
+		$('#sysmsgnum').empty();
+	} else {
+		let notificationCount = 0;
+		notifications.forEach(function (element) {
 // If notification codes are >CUSTON_NOTIFY means that are special codes to skip in this logic
-      if (element.code > CUSTOM_NOTIFY)
-        return;
+			if (element.code > CUSTOM_NOTIFY)
+				return;
 
-      tplNotify += `<a class="dropdown-item" href="javascript:NotificationDelete('${element.link}', ${element.code})">[${element.timestamp}] ${element.caption}<span class="ml-1 badge badge-danger">${element.count}</span></a>`;
-      notificationCount++;
-    });
+			tplNotify += `<a class="dropdown-item" href="javascript:NotificationDelete('${element.link}', ${element.code})">[${element.timestamp}] ${element.caption}<span class="ml-1 badge badge-danger">${element.count}</span></a>`;
+			notificationCount++;
+		});
 
-    htmlNotificationArea = `
+		htmlNotificationArea = `
 ${tplNotify}
 <a id="notification_area_deleteall" class="dropdown-item text-center" href="javascript:NotificationDelete('#', 0)" >Cancella tutto</a>
 `;
-    $('#notification_area_button').removeClass('disabled');
-    $('#sysmsgnum').html(notificationCount);
-  }
+		$('#notification_area_button').removeClass('disabled');
+		$('#sysmsgnum').html(notificationCount);
+	}
 
-  $('#notification_area').html(htmlNotificationArea);
+	$('#notification_area').html(htmlNotificationArea);
 }
 
 function refreshNotificationArea() {
-  fetch(`${BASEURL}/api.system.getserverstatus`, {headers: fetchHeaders})
-    .then(resp => {
-      if (resp.status === 200)
-        return resp.json();
-      else
-        return Promise.reject("getserverstatus: error");
-    })
-    .then(data => {
-      NotificationBuilder(data.notify);
-    })
-    .catch(err => {
-      console.log(err);
-    });
+	fetch(`${BASEURL}/api.system.getserverstatus`, {headers: fetchHeaders})
+		.then(resp => {
+			if (resp.status === 200)
+				return resp.json();
+			else
+				return Promise.reject("getserverstatus: error");
+		})
+		.then(data => {
+			NotificationBuilder(data.notify);
+		})
+		.catch(err => {
+			console.log(err);
+		});
 }
 
 function NotificationDelete(link, code) {
-  fetch(`${BASEURL}/api.system.removenotification/${code}`, {method: "POST"})
-    .then(() => {
-      if ((link != null) && (link.length != 0) && (link != '#'))
-        window.location.href = `${BASEURL}${link}`;
-    })
-    .catch(() => {
-      alert('NotificationDelete error');
-    });
+	fetch(`${BASEURL}/api.system.removenotification/${code}`, {method: "POST"})
+		.then(() => {
+			if ((link != null) && (link.length != 0) && (link != '#'))
+				window.location.href = `${BASEURL}${link}`;
+		})
+		.catch(() => {
+			alert('NotificationDelete error');
+		});
 }
 
 function SetupConfirmationDialog() {
-  $('.requestconfirm').on('click', function (ev) {
-    let confirmText = $(this).data('confirmtext');
-    if (!confirm(confirmText))
-      ev.preventDefault();
-  });
+	$('.requestconfirm').on('click', function (ev) {
+		let confirmText = $(this).data('confirmtext');
+		if (!confirm(confirmText))
+			ev.preventDefault();
+	});
 }
 
 function ForceFocus() {
-  setInterval(function () {
-    $("[forcefocus]").focus();
-  }, 1000);
+	setInterval(function () {
+		$("[forcefocus]").focus();
+	}, 1000);
 }
 
 $(function () {
-  SetupConfirmationDialog();
+	SetupConfirmationDialog();
 
-  refreshNotificationArea();
+	refreshNotificationArea();
 
-  ForceFocus(); // INPUT AUTOFOCUS
+	ForceFocus(); // INPUT AUTOFOCUS
 
-  $('body').on('submit', 'form', function () {
-    $('body').focus();
-    $('form input,form select').prop('readonly', true);
-    
-    // Manual submit for more control
-    this.submit();
-    return false;
-  });
+	$('body').on('submit', 'form', function () {
+		$('body').focus();
+		$('form input,form select').prop('readonly', true);
 
-  setInterval(() => {
-    refreshNotificationArea();
-  }, 3000);
+		// Manual submit for more control
+		this.submit();
+		return false;
+	});
+
+	setInterval(() => {
+		refreshNotificationArea();
+	}, 3000);
 });
 

+ 6 - 6
ui/login.tpl

@@ -1,16 +1,16 @@
 <div class="text-center mx-auto col-md-3 mt-3">
-	<img src="{{@BASEURL}}/ui/images/logo.png" alt="" class="img-fluid om-shadow">
-	<form enctype="multipart/form-data" action="loginform" method="POST">
+	<img alt="" class="img-fluid om-shadow" src="{{@BASEURL}}/ui/images/logo.png">
+	<form action="loginform" enctype="multipart/form-data" method="POST">
 		<h1 class="mb-4" style="font-size: 4vw">Login</h1>
 		<check if="{{ isset(@INFOTEXT) }}">
 			<div class="alert alert-danger" role="alert">
 				{{@INFOTEXT}}
 			</div>
 		</check>
-		<label for="username" class="sr-only">username</label>
-		<input type="text" name="username" id="username" class="form-control mb-1" placeholder="Username" required autocomplete="off">
-		<label for="password" class="sr-only">Password</label>
-		<input type="password" name="password" id="password" class="form-control mb-1" placeholder="Password" required autocomplete="off">
+		<label class="sr-only" for="username">username</label>
+		<input autocomplete="off" class="form-control mb-1" id="username" name="username" placeholder="Username" required type="text">
+		<label class="sr-only" for="password">Password</label>
+		<input autocomplete="off" class="form-control mb-1" id="password" name="password" placeholder="Password" required type="password">
 		<button class="btn btn-block" type="submit">Invia</button>
 	</form>
 </div>

+ 12 - 8
ui/masterpage.tpl

@@ -2,13 +2,13 @@
 <html lang="it">
 <head>
 	<meta charset="UTF-8">
-	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
+	<meta content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no" name="viewport">
 	<title>{{@SITENAME}}</title>
-	<link type="text/css" rel="stylesheet" href="{{@BASEURL}}/bundle.css?v={{@VERSION}}"/>
-	<link rel="shortcut icon" type="image/x-icon" href="{{@BASEURL}}/ui/favicon_{{@CUSTOMERNAME}}.ico?v={{@VERSION}}">
+	<link href="{{@BASEURL}}/bundle.css?v={{@VERSION}}" rel="stylesheet" type="text/css"/>
+	<link href="{{@BASEURL}}/ui/favicon_{{@CUSTOMERNAME}}.ico?v={{@VERSION}}" rel="shortcut icon" type="image/x-icon">
 
 	<script type="text/javascript">
-    const BASEURL = '{{@BASEURL}}';
+		const BASEURL = '{{@BASEURL}}';
 	</script>
 </head>
 <body>
@@ -16,7 +16,7 @@
 <include href="header.tpl"/>
 
 <div class="d-flex flex-row justify-content-around align-items-center" style="overflow-y: auto; height: calc(100% - 150px)">
-	<include if="{{isset(@CONTENT)}}" href="{{@CONTENT}}"/>
+	<include href="{{@CONTENT}}" if="{{isset(@CONTENT)}}"/>
 </div>
 
 <include href="footer.tpl"/>
@@ -26,9 +26,13 @@
 <check if="{{isset(@REQ_REDIRECT}})">
 	<true>
 		<script>
-      setTimeout(() => {
-        window.location.href = "{{@BASEURL}}/{{@REQ_REDIRECT}}";
-      }, {{@REQ_REDIRECT_MS}});
+			setTimeout(() => {
+				window.location.href = "{{@BASEURL}}/{{@REQ_REDIRECT}}";
+			}, {;
+			{@REQ_REDIRECT_MS
+			}
+			})
+
 		</script>
 	</true>
 </check>

+ 23 - 23
ui/unbind.tpl

@@ -1,25 +1,25 @@
 <div class="row h-100 justify-content-center">
-  <div class="col-md-10 align-self-center">
-    <form class="form" method="post" action="{{@BASEURL}}/unbind/{{@STEP+1}}">
-      <input type="submit" hidden id="submitform"/>
-      <input autofocus forcefocus type="text" name="labelid" class="form-control form-control" placeholder="Label ID" required autocomplete="off" value=""/>
-    </form>
-    <check if="{{ @STEP == 2 }}">
-      <div class="alert alert-info mt-5" role="alert">
-        Invio unbind
-      </div>
-      <check if="{{ isset(@INFOTEXT) }}">
-        <true>
-          <div class="alert alert-danger mt-3 text-center" role="alert">
-            {{@INFOTEXT}}
-          </div>
-        </true>
-        <false>
-          <script>
-            window.location.href = "{{@BASEURL}}/unbind/1";
-          </script>
-        </false>
-      </check>
-    </check>
-  </div>
+	<div class="col-md-10 align-self-center">
+		<form action="{{@BASEURL}}/unbind/{{@STEP+1}}" class="form" method="post">
+			<input hidden id="submitform" type="submit"/>
+			<input autocomplete="off" autofocus class="form-control form-control" forcefocus name="labelid" placeholder="Label ID" required type="text" value=""/>
+		</form>
+		<check if="{{ @STEP == 2 }}">
+			<div class="alert alert-info mt-5" role="alert">
+				Invio unbind
+			</div>
+			<check if="{{ isset(@INFOTEXT) }}">
+				<true>
+					<div class="alert alert-danger mt-3 text-center" role="alert">
+						{{@INFOTEXT}}
+					</div>
+				</true>
+				<false>
+					<script>
+						window.location.href = "{{@BASEURL}}/unbind/1";
+					</script>
+				</false>
+			</check>
+		</check>
+	</div>
 </div>

Some files were not shown because too many files changed in this diff