dolibarr  17.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 /* ******************************************************************** */
38 if (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
43 if (isset($_SERVER['WINDIR']) && @file_exists($_SERVER['WINDIR'])) {
44  $font_loc = $_SERVER['WINDIR'].'\Fonts\arialbd.ttf';
45 }
46 if (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 
59 if (defined('PHP-BARCODE_PATH_COMMAND')) {
60  $genbarcode_loc = constant('PHP-BARCODE_PATH_COMMAND');
61 } else {
62  $genbarcode_loc = '';
63  if (!empty($conf->global->GENBARCODE_LOCATION)) {
64  $genbarcode_loc = $conf->global->GENBARCODE_LOCATION;
65  }
66 }
67 
68 
69 
70 
80 function 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 
127 function 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 
175 function barcode_gen_ean_sum($ean)
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 
199 function barcode_gen_ean_bars($ean)
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 
229 function 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 
285 function 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 
335 function barcode_encode_genbarcode($code, $encoding)
336 {
337  global $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 = preg_replace("/[\\\|]/", "_", $encoding);
347  $code = preg_replace("/[\\\|]/", "_", $code);
348 
349  $command = escapeshellarg($genbarcode_loc);
350  //$paramclear=" \"".str_replace("\"", "\\\"",$code)."\" \"".str_replace("\"", "\\\"",strtoupper($encoding))."\"";
351  $paramclear = " ".escapeshellarg($code)." ".escapeshellarg(strtoupper($encoding));
352 
353  $fullcommandclear = $command." ".$paramclear." 2>&1";
354  //print $fullcommandclear."<br>\n";exit;
355 
356  dol_syslog("Run command ".$fullcommandclear);
357  $fp = popen($fullcommandclear, "r");
358  if ($fp) {
359  $bars = fgets($fp, 1024);
360  $text = fgets($fp, 1024);
361  $encoding = fgets($fp, 1024);
362  pclose($fp);
363  } else {
364  dol_syslog("barcode.lib.php::barcode_encode_genbarcode failed to run popen ".$fullcommandclear, LOG_ERR);
365  return false;
366  }
367  //var_dump($bars);
368  $ret = array(
369  "bars" => trim($bars),
370  "text" => trim($text),
371  "encoding" => trim($encoding),
372  "error" => ""
373  );
374  //var_dump($ret);
375  if (preg_match('/permission denied/i', $ret['bars'])) {
376  $ret['error'] = $ret['bars'];
377  $ret['bars'] = '';
378  return $ret;
379  }
380  if (!$ret['bars']) {
381  return false;
382  }
383  if (!$ret['text']) {
384  return false;
385  }
386  if (!$ret['encoding']) {
387  return false;
388  }
389  return $ret;
390 }
391 
403 function barcode_outimage($text, $bars, $scale = 1, $mode = "png", $total_y = 0, $space = '')
404 {
405  global $bar_color, $bg_color, $text_color;
406  global $font_loc, $filebarcode;
407 
408  //print "$text, $bars, $scale, $mode, $total_y, $space, $font_loc, $filebarcode<br>";
409  //var_dump($text);
410  //var_dump($bars);
411  //var_dump($font_loc);
412 
413  /* set defaults */
414  if ($scale < 1) {
415  $scale = 2;
416  }
417  $total_y = (int) $total_y;
418  if ($total_y < 1) {
419  $total_y = (int) $scale * 60;
420  }
421  if (!$space) {
422  $space = array('top'=>2 * $scale, 'bottom'=>2 * $scale, 'left'=>2 * $scale, 'right'=>2 * $scale);
423  }
424 
425  /* count total width */
426  $xpos = 0;
427  $width = true;
428  $ln = strlen($bars);
429  for ($i = 0; $i < $ln; $i++) {
430  $val = strtolower($bars[$i]);
431  if ($width) {
432  $xpos += $val * $scale;
433  $width = false;
434  continue;
435  }
436  if (preg_match("/[a-z]/", $val)) {
437  /* tall bar */
438  $val = ord($val) - ord('a') + 1;
439  }
440  $xpos += $val * $scale;
441  $width = true;
442  }
443 
444  /* allocate the image */
445  $total_x = ($xpos) + $space['right'] + $space['right'];
446  $xpos = $space['left'];
447  if (!function_exists("imagecreate")) {
448  print "You don't have the gd2 extension enabled<br>\n";
449  return "";
450  }
451  $im = imagecreate($total_x, $total_y);
452  /* create two images */
453  $col_bg = ImageColorAllocate($im, $bg_color[0], $bg_color[1], $bg_color[2]);
454  $col_bar = ImageColorAllocate($im, $bar_color[0], $bar_color[1], $bar_color[2]);
455  $col_text = ImageColorAllocate($im, $text_color[0], $text_color[1], $text_color[2]);
456  $height = round($total_y - ($scale * 10));
457  $height2 = round($total_y - $space['bottom']);
458 
459  /* paint the bars */
460  $width = true;
461  $ln = strlen($bars);
462  for ($i = 0; $i < $ln; $i++) {
463  $val = strtolower($bars[$i]);
464  if ($width) {
465  $xpos += $val * $scale;
466  $width = false;
467  continue;
468  }
469  if (preg_match("/[a-z]/", $val)) {
470  /* tall bar */
471  $val = ord($val) - ord('a') + 1;
472  $h = $height2;
473  } else {
474  $h = $height;
475  }
476  imagefilledrectangle($im, $xpos, $space['top'], $xpos + ($val * $scale) - 1, $h, $col_bar);
477  $xpos += $val * $scale;
478  $width = true;
479  }
480 
481  $chars = explode(" ", $text);
482  foreach ($chars as $v) {
483  if (trim($v)) {
484  $inf = explode(":", $v);
485  $fontsize = $scale * ($inf[1] / 1.8);
486  $fontheight = $total_y - ($fontsize / 2.7) + 2;
487  imagettftext($im, $fontsize, 0, $space['left'] + ($scale * $inf[0]) + 2, $fontheight, $col_text, $font_loc, $inf[2]);
488  }
489  }
490 
491  /* output the image */
492  $mode = strtolower($mode);
493  if ($mode == 'jpg' || $mode == 'jpeg') {
494  header("Content-Type: image/jpeg; name=\"barcode.jpg\"");
495  imagejpeg($im);
496  } elseif ($mode == 'gif') {
497  header("Content-Type: image/gif; name=\"barcode.gif\"");
498  imagegif($im);
499  } elseif (!empty($filebarcode)) {
500  // To wxrite into afile onto disk
501  imagepng($im, $filebarcode);
502  } else {
503  header("Content-Type: image/png; name=\"barcode.png\"");
504  imagepng($im);
505  }
506 }
barcode_encode_genbarcode($code, $encoding)
Encode result of genbarcode command.
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.
barcode_encode($code, $encoding)
Encodes $code with $encoding using genbarcode OR built-in encoder if you don't have genbarcode only E...
if(!empty($conf->global->GENBARCODE_LOCATION)) barcode_print($code, $encoding="ANY", $scale=2, $mode="png")
Print barcode.
Definition: barcode.lib.php:80
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.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.