dolibarr 19.0.4
barcode.lib.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2004-2010 Folke Ashberg: Some lines of code were inspired from work
4 * of Folke Ashberg into PHP-Barcode 0.3pl2, available as GPL
5 * source code at http://www.ashberg.de/bar.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
27/* ******************************************************************** */
28/* COLORS */
29/* ******************************************************************** */
30$bar_color = array(0, 0, 0);
31$bg_color = array(255, 255, 255);
32$text_color = array(0, 0, 0);
33
34
35/* ******************************************************************** */
36/* FONT FILE */
37/* ******************************************************************** */
38if (defined('DOL_DEFAULT_TTF_BOLD')) {
39 $font_loc = constant('DOL_DEFAULT_TTF_BOLD');
40}
41// Automatic-Detection of Font if running Windows
42// @CHANGE LDR
43if (isset($_SERVER['WINDIR']) && @file_exists($_SERVER['WINDIR'])) {
44 $font_loc = $_SERVER['WINDIR'].'\Fonts\arialbd.ttf';
45}
46if (empty($font_loc)) {
47 die('DOL_DEFAULT_TTF_BOLD must de defined with full path to a TTF font.');
48}
49
50
51/* ******************************************************************** */
52/* GENBARCODE */
53/* ******************************************************************** */
54/* location of 'genbarcode'
55 * leave blank if you don't have them :(
56* genbarcode is needed to render encodings other than EAN-12/EAN-13/ISBN
57*/
58
59if (defined('PHP-BARCODE_PATH_COMMAND')) {
60 $genbarcode_loc = constant('PHP-BARCODE_PATH_COMMAND');
61} else {
62 $genbarcode_loc = '';
63 if (getDolGlobalString('GENBARCODE_LOCATION')) {
64 $genbarcode_loc = $conf->global->GENBARCODE_LOCATION;
65 }
66}
67
68
69
70
80function barcode_print($code, $encoding = "ANY", $scale = 2, $mode = "png")
81{
82 dol_syslog("barcode.lib.php::barcode_print $code $encoding $scale $mode");
83
84 $bars = barcode_encode($code, $encoding);
85 if (!$bars || !empty($bars['error'])) {
86 // Return error message instead of array
87 if (empty($bars['error'])) {
88 $error = 'Bad Value '.$code.' for encoding '.$encoding;
89 } else {
90 $error = $bars['error'];
91 }
92 dol_syslog('barcode.lib.php::barcode_print '.$error, LOG_ERR);
93 return $error;
94 }
95 if (!$mode) {
96 $mode = "png";
97 }
98 //if (preg_match("/^(text|txt|plain)$/i",$mode)) print barcode_outtext($bars['text'],$bars['bars']);
99 //elseif (preg_match("/^(html|htm)$/i",$mode)) print barcode_outhtml($bars['text'],$bars['bars'], $scale,0, 0);
100 //else
101 barcode_outimage($bars['text'], $bars['bars'], $scale, $mode);
102 return $bars;
103}
104
127function barcode_encode($code, $encoding)
128{
129 global $genbarcode_loc;
130
131 if ((preg_match("/^upc$/i", $encoding))
132 && (preg_match("/^[0-9]{11,12}$/", $code))
133 ) {
134 /* use built-in UPC-Encoder */
135 dol_syslog("barcode.lib.php::barcode_encode Use barcode_encode_upc");
136 $bars = barcode_encode_upc($code, $encoding);
137 } elseif ((preg_match("/^ean$/i", $encoding))
138
139 || (($encoding) && (preg_match("/^isbn$/i", $encoding))
140 && ((strlen($code) == 9 || strlen($code) == 10) ||
141 (((preg_match("/^978/", $code) && strlen($code) == 12) ||
142 (strlen($code) == 13)))))
143
144 || ((!isset($encoding) || !$encoding || (preg_match("/^ANY$/i", $encoding)))
145 && (preg_match("/^[0-9]{12,13}$/", $code)))
146 ) {
147 /* use built-in EAN-Encoder */
148 dol_syslog("barcode.lib.php::barcode_encode Use barcode_encode_ean");
149 $bars = barcode_encode_ean($code, $encoding);
150 } elseif (file_exists($genbarcode_loc)) { // For example C39
151 /* use genbarcode */
152 dol_syslog("barcode.lib.php::barcode_encode Use genbarcode ".$genbarcode_loc." code=".$code." encoding=".$encoding);
153 $bars = barcode_encode_genbarcode($code, $encoding);
154 } else {
155 print "barcode_encode needs an external program for encodings other then EAN/ISBN (code=".dol_escape_htmltag($code).", encoding=".dol_escape_htmltag($encoding).")<BR>\n";
156 print "<UL>\n";
157 print "<LI>download gnu-barcode from <A href=\"https://www.gnu.org/software/barcode/\">www.gnu.org/software/barcode/</A>\n";
158 print "<LI>compile and install them\n";
159 print "<LI>specify path the genbarcode in barcode module setup\n";
160 print "</UL>\n";
161 print "<BR>\n";
162 return false;
163 }
164
165 return $bars;
166}
167
168
176{
177 $even = true;
178 $esum = 0;
179 $osum = 0;
180 $ln = strlen($ean) - 1;
181 for ($i = $ln; $i >= 0; $i--) {
182 if ($even) {
183 $esum += $ean[$i];
184 } else {
185 $osum += $ean[$i];
186 }
187 $even = !$even;
188 }
189 return (10 - ((3 * $esum + $osum) % 10)) % 10;
190}
191
192
200{
201 $digits = array(3211, 2221, 2122, 1411, 1132, 1231, 1114, 1312, 1213, 3112);
202 $mirror = array("000000", "001011", "001101", "001110", "010011", "011001", "011100", "010101", "010110", "011010");
203 $guards = array("9a1a", "1a1a1", "a1a7");
204
205 $line = $guards[0];
206 for ($i = 1; $i < 13; $i++) {
207 $str = $digits[$ean[$i]];
208 if ($i < 7 && $mirror[$ean[0]][$i - 1] == 1) {
209 $line .= strrev($str);
210 } else {
211 $line .= $str;
212 }
213 if ($i == 6) {
214 $line .= $guards[1];
215 }
216 }
217 $line .= $guards[2];
218
219 return $line;
220}
221
229function barcode_encode_ean($ean, $encoding = "EAN-13")
230{
231 $ean = trim($ean);
232 if (preg_match("/[^0-9]/i", $ean)) {
233 return array("error"=>"Invalid encoding/code. encoding=".$encoding." code=".$ean." (not a numeric)", "text"=>"Invalid encoding/code. encoding=".$encoding." code=".$ean." (not a numeric)");
234 }
235 $encoding = strtoupper($encoding);
236 if ($encoding == "ISBN") {
237 if (!preg_match("/^978/", $ean)) {
238 $ean = "978".$ean;
239 }
240 }
241 if (preg_match("/^97[89]/", $ean)) {
242 $encoding = "ISBN";
243 }
244 if (strlen($ean) < 12 || strlen($ean) > 13) {
245 return array("error"=>"Invalid encoding/code. encoding=".$encoding." code=".$ean." (must have 12/13 numbers)", "text"=>"Invalid encoding/code. encoding=".$encoding." code=".$ean." (must have 12/13 numbers)");
246 }
247
248 $ean = substr($ean, 0, 12);
249 $eansum = barcode_gen_ean_sum($ean);
250 $ean .= $eansum;
251 $bars = barcode_gen_ean_bars($ean);
252
253 /* create text */
254 $pos = 0;
255 $text = "";
256 for ($a = 0; $a < 13; $a++) {
257 if ($a > 0) {
258 $text .= " ";
259 }
260 $text .= $pos.":12:".$ean[$a];
261 if ($a == 0) {
262 $pos += 12;
263 } elseif ($a == 6) {
264 $pos += 12;
265 } else {
266 $pos += 7;
267 }
268 }
269
270 return array(
271 "error" => '',
272 "encoding" => $encoding,
273 "bars" => $bars,
274 "text" => $text
275 );
276}
277
285function barcode_encode_upc($upc, $encoding = "UPC")
286{
287 $upc = trim($upc);
288 if (preg_match("/[^0-9]/i", $upc)) {
289 return array("error"=>"Invalid encoding/code. encoding=".$encoding." code=".$upc." (not a numeric)", "text"=>"Invalid encoding/code. encoding=".$encoding." code=".$upc." (not a numeric)");
290 }
291 $encoding = strtoupper($encoding);
292 if (strlen($upc) < 11 || strlen($upc) > 12) {
293 return array("error"=>"Invalid encoding/code. encoding=".$encoding." code=".$upc." (must have 11/12 numbers)", "text"=>"Invalid encoding/code. encoding=".$encoding." code=".$upc." (must have 11/12 numbers)");
294 }
295
296 $upc = substr("0".$upc, 0, 12);
297 $eansum = barcode_gen_ean_sum($upc);
298 $upc .= $eansum;
299 $bars = barcode_gen_ean_bars($upc);
300
301 /* create text */
302 $pos = 0;
303 $text = "";
304 for ($a = 1; $a < 13; $a++) {
305 if ($a > 1) {
306 $text .= " ";
307 }
308 $text .= $pos.":12:".$upc[$a];
309 if ($a == 1) {
310 $pos += 15;
311 } elseif ($a == 6) {
312 $pos += 17;
313 } elseif ($a == 11) {
314 $pos += 15;
315 } else {
316 $pos += 7;
317 }
318 }
319
320 return array(
321 "error" => '',
322 "encoding" => $encoding,
323 "bars" => $bars,
324 "text" => $text
325 );
326}
327
335function barcode_encode_genbarcode($code, $encoding)
336{
337 global $conf, $db, $genbarcode_loc;
338
339 // Clean parameters
340 if (preg_match("/^ean$/i", $encoding) && strlen($code) == 13) {
341 $code = substr($code, 0, 12);
342 }
343 if (!$encoding) {
344 $encoding = "ANY";
345 }
346 $encoding = dol_string_nospecial($encoding, '_');
347 $code = dol_string_nospecial($code, "_");
348
349 $command = escapeshellarg($genbarcode_loc);
350 $paramclear = " ".escapeshellarg($code)." ".escapeshellarg(strtoupper($encoding));
351
352 $fullcommandclear = $command." ".$paramclear." 2>&1";
353 //print $fullcommandclear."<br>\n";exit;
354
355 dol_syslog("Run command ".$fullcommandclear);
356
357 $outputfile = $conf->user->dir_temp.'/genbarcode.tmp'; // File used with popen method
358
359 // Execute a CLI
360 include_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php';
361 $utils = new Utils($db);
362 $result = $utils->executeCLI($fullcommandclear, $outputfile);
363
364 if (!empty($result['output'])) {
365 $tmparr = explode("\n", $result['output']);
366 $bars = $tmparr[0];
367 $text = $tmparr[1];
368 $encoding = $tmparr[2];
369 } else {
370 dol_syslog("barcode.lib.php::barcode_encode_genbarcode failed to run ".$fullcommandclear, LOG_ERR);
371 return false;
372 }
373
374 //var_dump($bars);
375 $ret = array(
376 "bars" => trim($bars),
377 "text" => trim($text),
378 "encoding" => trim($encoding),
379 "error" => ""
380 );
381 //var_dump($ret);
382 if (preg_match('/permission denied/i', $ret['bars'])) {
383 $ret['error'] = $ret['bars'];
384 $ret['bars'] = '';
385 return $ret;
386 }
387 if (!$ret['bars']) {
388 return false;
389 }
390 if (!$ret['text']) {
391 return false;
392 }
393 if (!$ret['encoding']) {
394 return false;
395 }
396 return $ret;
397}
398
410function barcode_outimage($text, $bars, $scale = 1, $mode = "png", $total_y = 0, $space = '')
411{
412 global $bar_color, $bg_color, $text_color;
413 global $font_loc, $filebarcode;
414
415 //print "$text, $bars, $scale, $mode, $total_y, $space, $font_loc, $filebarcode<br>";
416 //var_dump($text);
417 //var_dump($bars);
418 //var_dump($font_loc);
419
420 /* set defaults */
421 if ($scale < 1) {
422 $scale = 2;
423 }
424 $total_y = (int) $total_y;
425 if ($total_y < 1) {
426 $total_y = (int) $scale * 60;
427 }
428 if (!$space) {
429 $space = array('top'=>2 * $scale, 'bottom'=>2 * $scale, 'left'=>2 * $scale, 'right'=>2 * $scale);
430 }
431
432 /* count total width */
433 $xpos = 0;
434 $width = true;
435 $ln = strlen($bars);
436 for ($i = 0; $i < $ln; $i++) {
437 $val = strtolower($bars[$i]);
438 if ($width) {
439 $xpos += $val * $scale;
440 $width = false;
441 continue;
442 }
443 if (preg_match("/[a-z]/", $val)) {
444 /* tall bar */
445 $val = ord($val) - ord('a') + 1;
446 }
447 $xpos += $val * $scale;
448 $width = true;
449 }
450
451 /* allocate the image */
452 $total_x = ($xpos) + $space['right'] + $space['right'];
453 $xpos = $space['left'];
454 if (!function_exists("imagecreate")) {
455 print "You don't have the gd2 extension enabled<br>\n";
456 return "";
457 }
458 $im = imagecreate($total_x, $total_y);
459 /* create two images */
460 $col_bg = ImageColorAllocate($im, $bg_color[0], $bg_color[1], $bg_color[2]);
461 $col_bar = ImageColorAllocate($im, $bar_color[0], $bar_color[1], $bar_color[2]);
462 $col_text = ImageColorAllocate($im, $text_color[0], $text_color[1], $text_color[2]);
463 $height = round($total_y - ($scale * 10));
464 $height2 = round($total_y - $space['bottom']);
465
466 /* paint the bars */
467 $width = true;
468 $ln = strlen($bars);
469 for ($i = 0; $i < $ln; $i++) {
470 $val = strtolower($bars[$i]);
471 if ($width) {
472 $xpos += $val * $scale;
473 $width = false;
474 continue;
475 }
476 if (preg_match("/[a-z]/", $val)) {
477 /* tall bar */
478 $val = ord($val) - ord('a') + 1;
479 $h = $height2;
480 } else {
481 $h = $height;
482 }
483 imagefilledrectangle($im, $xpos, $space['top'], $xpos + ($val * $scale) - 1, $h, $col_bar);
484 $xpos += $val * $scale;
485 $width = true;
486 }
487
488 $chars = explode(" ", $text);
489 foreach ($chars as $v) {
490 if (trim($v)) {
491 $inf = explode(":", $v);
492 $fontsize = $scale * ($inf[1] / 1.8);
493 $fontheight = $total_y - ($fontsize / 2.7) + 2;
494 imagettftext($im, $fontsize, 0, $space['left'] + ($scale * $inf[0]) + 2, $fontheight, $col_text, $font_loc, $inf[2]);
495 }
496 }
497
498 /* output the image */
499 $mode = strtolower($mode);
500 if ($mode == 'jpg' || $mode == 'jpeg') {
501 header("Content-Type: image/jpeg; name=\"barcode.jpg\"");
502 imagejpeg($im);
503 } elseif ($mode == 'gif') {
504 header("Content-Type: image/gif; name=\"barcode.gif\"");
505 imagegif($im);
506 } elseif (!empty($filebarcode)) {
507 // To wxrite into afile onto disk
508 imagepng($im, $filebarcode);
509 } else {
510 header("Content-Type: image/png; name=\"barcode.png\"");
511 imagepng($im);
512 }
513}
514
521function isAValidEAN13($ean)
522{
523 $sumEvenIndexes = 0;
524 $sumOddIndexes = 0;
525
526 $eanAsArray = array_map('intval', str_split($ean));
527
528 if (!(count($eanAsArray) === 13)) {
529 return false;
530 };
531
532 $num = (count($eanAsArray) - 1);
533 for ($i = 0; $i < $num; $i++) {
534 if ($i % 2 === 0) {
535 $sumOddIndexes += $eanAsArray[$i];
536 } else {
537 $sumEvenIndexes += $eanAsArray[$i];
538 }
539 }
540
541 $rest = ($sumOddIndexes + (3 * $sumEvenIndexes)) % 10;
542
543 if ($rest !== 0) {
544 $rest = 10 - $rest;
545 }
546
547 return $rest === $eanAsArray[12];
548}
barcode_encode_genbarcode($code, $encoding)
Encode result of genbarcode command.
if(getDolGlobalString( 'GENBARCODE_LOCATION')) barcode_print($code, $encoding="ANY", $scale=2, $mode="png")
Print barcode.
barcode_gen_ean_sum($ean)
Calculate EAN sum.
barcode_encode_upc($upc, $encoding="UPC")
Encode UPC.
barcode_gen_ean_bars($ean)
Generate EAN bars.
barcode_encode_ean($ean, $encoding="EAN-13")
Encode EAN.
isAValidEAN13($ean)
Check if EAN13 code is valid.
barcode_encode($code, $encoding)
Encodes $code with $encoding using genbarcode OR built-in encoder if you don't have genbarcode only E...
barcode_outimage($text, $bars, $scale=1, $mode="png", $total_y=0, $space='')
Output image onto standard output, or onto disk if global filebarcode is defined.
Class to manage utility methods.
dol_string_nospecial($str, $newstr='_', $badcharstoreplace='', $badcharstoremove='', $keepspaces=0)
Clean a string from all punctuation characters to use it as a ref or login.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...